r = /
(?<= # begin a positive lookbehind
\b # match a (zero-width) word break
foo # match string
[ ] # match a space
) # close positive lookbehind
.*? # match zero or more chars, non-greedily
(?= # begin a positive lookahead
\n # match newline char
[ ]{2} # match two spaces
\w # match a word char
) # close positive lookahead
/xm # free-spacing and multiline modes
code[r]
#=> "an arbitrary statement\n that could go on for \n several lines"
Обычное выражение для регулярного выражения выглядит следующим образом.
/(?<=\bfoo ).*?(?=\n \w)/m
Обратите внимание, что в режиме свободного пробела я сопоставлял пробелы с классом символов, содержащим один пробел ([ ]
). Если бы я использовал пробелы, как я делал в регулярном выражении непосредственно выше, они были бы удалены, потому что я использовал режим свободный интервал для определения регулярного выражения, которое игнорирует пробелы.
Важно, чтобы выражение, которое захватывает возвращаемую строку, было нежадным (.*?
вместо .*
). Если бы он был жадным (.*
), мы получили бы ошибочный результат, как показано на следующем примере:
str = "foo oh my\n a\n b\n c"
str[r]
#=> "oh my"
str[/(?<=\bfoo ).*(?=\n \w)/m]
#=> "oh my\n a\n b"
В жадном случае .*
поглощает столько, сколько в банке, пока не дойдет до последнего возможного совпадения положительного взгляда (?=\n \w)
, а именно "\n c"
.
разрыв слова (\b
) должен гарантировать, что мы не совпадаем, например, "snafoo"
. Требуется, чтобы "foo"
предшествовал несловесный символ или был первый символ строки.
Другой способ написания регулярного выражения заключается в следующем.
code[/\bfoo \K.*?(?=\n \w)/m]
#=> "an arbitrary statement\n that could go on for \n several lines"
\K
можно прочитать, "отбросить все совпадения при возврате сопоставленной строки". То есть, часть перед \K
должна совпадать; он просто не используется при формировании совпавшей строки, которая возвращается.
Последний способ написать регулярное выражение - использовать группу захвата.
code[/\bfoo (.*?)\n \w/m, 1]
#=> "an arbitrary statement\n that could go on for \n several lines"
Интересующая строка записывается в группу захвата 1
, а затем возвращается в необязательном втором аргументе String # [] .
Наконец, обратите внимание, что \w
ближе к концу имеет тот же эффект, что и \w+
.