我正在尝试匹配一些文本,如果它附近没有另一个文本块。例如,如果"bar"
不在"foo"
之前,我想匹配"bar"
。我可以匹配"foo"
如果/(?<!foo)bar/
>
"foo 12345 bar"
但我也想不匹配/(?<!foo.{1,10})bar/
。我试过了:
{{1}}
但使用通配符+范围似乎是Ruby中的无效正则表达式。我在想这个问题错了吗?
答案 0 :(得分:12)
你正在考虑正确的方法。但不幸的是,后视镜通常具有固定长度。唯一的主要例外是.NET的正则表达式引擎,它允许在lookbehinds内部重复量词。但是,因为你只需要一个消极的外观,而不是前瞻。有一个黑客为你。反转字符串,然后尝试匹配:
/rab(?!.{0,10}oof)/
然后反转匹配的结果或从字符串的长度中减去匹配的位置,如果这就是你所追求的。
现在从你给出的正则表达式,我想这只是你真正需要的简化版本。当然,如果bar
本身就是一个复杂的模式,那么需要更多考虑如何正确地反转它。
请注意,如果您的模式需要可变长度的lookbehinds和lookaheads,那么解决这个问题会更难。此外,在您的情况下,可以将您的lookbehind解构为多个可变长度的(因为您既不使用+
也不使用*
):
/(?<!foo)(?<!foo.)(?<!foo.{2})(?<!foo.{3})(?<!foo.{4})(?<!foo.{5})(?<!foo.{6})(?<!foo.{7})(?<!foo.{8})(?<!foo.{9})(?<!foo.{10})bar/
但那不是那么好,是吗?
答案 1 :(得分:3)
正如m.buettner已经提到的,Ruby正则表达式中的lookbehind必须具有固定的长度,并在文档中进行了描述。所以,你不能把量词放在后面。
您无需一步检查所有内容。尝试执行多个正则表达式匹配步骤以获得所需内容。假设在foo
的单个实例前面存在bar
会破坏条件,无论是否有另一个bar
,那么
string.match(/bar/) and !string.match(/foo.*bar/)
将为您提供您想要的示例。
如果您希望匹配在bar foo bar
成功,那么您可以执行此操作
string.scan(/foo|bar/).first == "bar"