Я предполагаю (частично из-за примера в вопросе), что совпадения должны исключать строки, начинающиеся с "{{" и заканчивающиеся "}}", содержащие "|", которые также содержат "{{".Например, ни
"{{ a | {{ b }}"
, ни
"{{ a | {{ b }} c }}"
не должны совпадать.Если они должны быть сопоставлены, можно использовать регулярное выражение, предложенное @ WiktorStribiżew в комментарии к вопросу.
Вы можете получить желаемые соответствия следующим образом.
str = "Testing some text {{ first_name | mask }} and another {{ city }} " +
"and again {{ state | mask_trail }}"
R = /
{{ # match '{{'
((?!{{).) # match one character not preceded by '{{'. Save in capture group 1
* # perform capture to group 1 zero or more times
\| # match '|'
\g<1> # execute subroutine defined by capture group 1
* # perform preceding match zero or more times
}} # match '}}'
/x # free-spacing regex definition mode
или,в кратком виде,
R = /{{((?!{{).)*\|\g<1>*}}/
str.gsub(R).to_a
#=> ["{{ first_name | mask }}", "{{ state | mask_trail }}"]
Я не смог использовать String # scan , потому что я не хотел возвращать содержимоеиз группы захвата.Поэтому я использовал String # gsub без блока, чтобы вернуть перечислитель, который генерирует совпадения, а затем преобразовал его в массив совпадений. Здесь - это обсуждение подпрограмм регулярного выражения или подвыражений.
Я позаимствовал (?!{{).
из ответа @ Pushpesh.