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