可变长度的后视镜

时间:2015-07-30 15:37:42

标签: ruby regex

好的,我的正则表达式是匹配鱼和青蛙,除非鱼或青蛙先于猫

/(?<!cat\s)f(ish|rog)/

的字符串:

foo catfish       # match fish (want total non-match)
fooxcat fish      # total non-match (yay)
foo cat frog      # total non-match (yay)
foo cat    fish   # match fish (want total non-match)
foo cat    frog   # match frog (want total non-match)
foo dog fish frog # match fish and frog (yay)
fooxfish          # match fish (yay)
foo frog          # match frog (yay)

正如你所看到的,除非猫和青蛙/鱼之间有零个或多个空白字符,否则正则表达式完美无缺。所以从逻辑上讲,在我的负面观察中添加零个或多个空白字符应该可以解决这个问题:

/(?<!cat\s*)f(ish|rog)/

不幸的是,可变长度的外观无效。

如何将上述内容翻译成有效的正则表达式,或者是否有一个允许我使用可变长度后视镜的gem?

(更新青蛙到rog)

尝试失败:

2 个答案:

答案 0 :(得分:4)

您可以使用交替运算符。

cat\s*f(?:ish|rog)|(f(?:ish|rog))

DEMO

string.scan(/cat\s*f(?:ish|rog)|(f(?:ish|rog))/)

答案 1 :(得分:1)

以下是一些方法。

首先,进行测试:

def test
  result =
  [
    ['foo catfish',       false], 
    ['fooxcat fish',      false],
    ['foo cat frog',      false],
    ['foo cat    fish',   false],
    ['foo cat    frog',   false],
    ['foo dog fish frog', true ],
    ['fooxfish',          true ],
    ['foo frog cat',      true ],
  ].find { |str, res| check_it(str) != res }
  result ? (puts result; false) : true
end

#1最简单的正则表达式

def check_it(str)
  word = str[/cat|fish|frog/] 
  word && word != 'cat'
end

test #=> true

'cat'必须是第一个!

#2分而治之

def check_it(str)
  off = (str =~ /cat/)
  off = str.size unless off 
  !!(str[0, off] =~ /fish|frog/)
end

test #=> true