Я хотел бы заменить в этом выражении только группу в скобках:
my_string.gsub(/<--MARKER_START-->(.)*<--MARKER_END-->/, 'replace_text')
так что я получаю: <--MARKER_START-->replace_text<--MARKER_END-->
Я знаю, что могу повторить все блоки MARKER_START и MARKER_END в выражении подстановки, но я подумал, что должен быть более простой способ сделать это.

Вы можете сделать что-то вроде этого:
my_string.gsub(/(<--MARKER_START-->)(.*)(<--MARKER_END-->)/, 'replace_text')
Правда, вообще лучше бы не жадный матч. Я оставлю это на усмотрение Пьера, поскольку это может или не может быть применимо к его ситуации.
Я просто хочу добавить, что важно использовать одинарные кавычки (') в тексте замены (как в ответе). У меня возникли ошибки при использовании двойных кавычек (")
Вы можете сделать это с помощью утверждения просмотра вперед и назад с нулевой шириной.
Это регулярное выражение должно работать в ruby 1.9, perl и многих других местах:
Примечание. Ruby 1.8 поддерживает только утверждения с опережением. Чтобы сделать это правильно, вам нужно как смотреть вперед, так и назад.
s.gsub( /(?<=<--MARKER START-->).*?(?=<--MARKER END-->)/, 'replacement text' )
Что происходит в Ruby 1.8, так это то, что ?<= вызывает сбой, потому что он не понимает утверждения о ретроспективе. Для этого вам нужно вернуться к использованию обратной ссылки, например Грейг Хьюгилл упоминает
так что вы получаете
s.gsub( /(<--MARKER START-->).*?(?=<--MARKER END-->)/, 'replacement text' )
Я заменил (.)* в середине вашего регулярного выражения на .*? - это не жадно.
Если у вас нет не жадного, то ваше регулярное выражение будет пытаться сопоставить столько, сколько может - если у вас есть 2 маркера в одной строке, это пойдет не так. Лучше всего это проиллюстрировать на примере:
"<b>One</b> Two <b>Three</b>".gsub( /<b>.*</b>/, 'BOLD' )
=> "BOLD"
Что мы на самом деле хотим:
"<b>One</b> Two <b>Three</b>".gsub( /<b>.*?</b>/, 'BOLD' )
=> "BOLD Two BOLD"
Утверждение с нулевой шириной заглядывания в будущее звучит как гигантская куча ботанической путаницы.
На самом деле «прогнозируемое утверждение» означает: «Только совпадение, если то, что мы ищем, сопровождается другими вещами.
Например, соответствует цифре только в том случае, если за ней следует F.
"123F" =~ /\d(?=F)/ # will match the 3, but not the 1 or the 2
На самом деле «нулевая ширина» означает «учитывайте в нашем поиске ', за которым следует', но не учитывайте его как часть совпадения при замене, группировке или подобных вещах. Используя тот же пример 123F, если мы не использовали утверждение lookahead, а вместо этого просто сделаем это:
"123F" =~ /\dF/ # will match 3F, because F is considered part of the match
Как видите, это идеально подходит для проверки нашего <--MARKER END-->, но что нам нужно для <--MARKER START-->, так это возможность сказать: «Только совпадение, если то, что мы ищем, СЛЕДУЕТ за другими вещами». Это называется ретроспективным утверждением, которого в Ruby 1.8 нет по какой-то странной причине.
Надеюсь, это имеет смысл :-)
PS: Зачем использовать утверждения с опережением, а не просто обратные ссылки? Если вы используете опережающий просмотр, вы фактически не заменяете биты <--MARKER-->, а только содержимое. Если вы используете обратные ссылки, вы заменяете всю партию. Я не знаю, сильно ли это сказывается на производительности, но с точки зрения программирования это кажется правильным, поскольку на самом деле мы вообще не хотим заменять маркеры.
Отличный ответ, сохраняю на будущее :)
Вам действительно нужен не жадный. * Совпадение там посередине. Смотри мой ответ