Ruby正则表达式:用新行捕获点有条件地跟随另一个表达式

时间:2015-11-09 03:05:42

标签: ruby regex regex-lookarounds

我有一个多行字符串,我需要捕获一个包含换行符的表达式,但只能找到可能存在或不存在的另一个表达式。

示例字符串:

FOO
Hello
world
BAR
Hello

在这里,我想捕捉" Hello world" (包括新行),我可以用

/FOO(.*)BAR/m

BAR可能在字符串中,也可能不在字符串中。因此,我倾向于使BAR成为非捕获组,可能与?不同,例如:

/FOO(.*)(?:BAR)?/m

但这会捕获尾随的BARHello。其他尝试包括仅为点指定m模式,与

一样
/FOO(?m:(.*))(?:BAR)?/

但这也存在同样的问题。

对于那些慷慨帮助我的人,你可以使用http://rubular.com/来测试Ruby中的正则表达式。谢谢!

2 个答案:

答案 0 :(得分:2)

选项1 - 否定前瞻

使.*匹配除BAR之外的任何内容。表达式:

(?:(?!BAR).)*

使用negative lookahead创建类型的循环检查,在匹配每个字符之前,它不会跟BAR

<强>正则表达式

/FOO((?:(?!BAR).)*)/m

rubular demo

选项2 - 懒惰量词

您还可以使用lazy quantifier .*尽可能少地.*?匹配(请注意额外的?)。并要求表达式匹配BAR\z字符串的结尾。

<强>正则表达式

/FOO(.*?)(?:BAR|\z)/m

rubular demo

答案 1 :(得分:0)

  

$'跟随上次成功匹配的字符串   模式匹配

strs = [
  "",
  "FOO\nHello\nworld\nBAR\nHello",
  "FOOxxxBAR...FOOyyyBAR",
  "FOO\nHello\nworld\nHello",
  "FOOxxxxxxxFOOyyyBAR",
]

strs.each do |str|
  str.scan('FOO') do 
    p $'.split('BAR').first if $'
  end
end

--output:--
"xxx"
"yyy"
"\nHello\nworld\nHello"
"xxxxxxxFOOyyy"
"yyy"