【问题标题】:Multi-Line Regex: Find A where B is absent多行正则表达式:在 B 不存在的地方查找 A
【发布时间】:2013-03-06 16:17:56
【问题描述】:

我最近在 Regex 上浏览了很多,并且看到了很多涉及匹配一个单词的答案,而第二个单词则不存在。我见过很多Regex Examples,我可以在其中使用正则表达式搜索给定的单词(或任何更复杂的正则表达式)并找到缺少单词的位置。

在逐行的基础上看起来效果很好,但是在包含多行模式后,它似乎仍然无法正确匹配。

Example:匹配包含单词foo,但文件中没有单词bar 的整个文件字符串。到目前为止,我所拥有的是(?m)^(?=.*?(foo))((?!bar).)*$,它基于example link。我一直在使用 Ruby 正则表达式测试器进行测试,但我认为这是一个开放式正则表达式问题/问题。它似乎匹配较小的部分,我想让它在整个字符串上匹配/不匹配作为一个大块。

在上面提供的示例中,似乎是逐行查找匹配项。需要对正则表达式进行哪些更改才能应用于整个字符串?

编辑:我知道还有其他更有效的方法可以解决这个问题,而无需使用正则表达式。我不是在寻找使用其他方式解决问题的方法,而是从理论正则表达式的角度提出问题。它有一个多行模式(看起来“工作”),它有负/正搜索,可以逐行组合,为什么组合这两个原则不会产生预期的结果?

【问题讨论】:

  • 如果你不关心匹配返回什么,只是想知道 if 它匹配,你不能使用简单的字符串搜索功能两次吗? (一个用于foo,一个用于bar)?
  • 这个用例在 Eclipse 中的一个非常大的文件集上。使用 Eclipses 内置的搜索功能,您可以使用正则表达式搜索文件。搜索/比较这两组结果会很棘手,其中正则表达式可用于组合查询并仅查找与 foo 相关的文件,而无需参考 bar。 (“搜索 > 文件...”)。与它给出的当前结果相反,正则表达式还缺少什么来给它整个文件搜索,这真的更理论上更明智。我知道可能还有其他搜索方式,但它针对的是正则表达式解决方案。
  • 我在正则表达式方面的能力并不强,但是我知道 $ 意味着无论如何你都停在行尾。我也知道在 Ruby \m 最后会包装正则表达式。除此之外,如何修复正则表达式,我不确定
  • @JustinPihony 开头的(?m) 做同样的事情。这应该打开“多行模式”,告诉像 ^$ 这样的锚扩展过去的新行。这就是提出这个问题的地方,多线模式为什么不能正常工作。与 OP 中的示例相比,examplem 移到后面返回相同的结果。删除 m 确实会改变结果,但仍然不正确。
  • 这不是您可能正在寻找的解决方案,但我在所有实现中使用多行正则表达式总是遇到麻烦,最后用gsub('\n', ????).do_what_i_want.gsub(????, '\n') 作弊。

标签: ruby regex


【解决方案1】:

Sawa 的回答可以简化,只需要一个肯定的前瞻,一个否定的前瞻,并且由于您处于多行模式,.* 会负责其余的工作:

/(?=.*foo)(?!.*bar).*/m

多行表示. 也匹配\n,并且匹配是贪婪的。所以整个字符串将匹配而不需要锚。

更新

@Sawa 指出\A 是必要的,而不是\Z。 实际上,再看一遍,正面的前瞻似乎是不必要的:

/\A(?!.*bar).*foo.*/m

【讨论】:

  • 这不起作用。它将错误地匹配"bar foo" 的(一部分)。这就是为什么我的正则表达式有锚来确保负前瞻影响整个字符串。
【解决方案2】:

匹配不包括foo 的整个字符串的正则表达式是:

/\A(?!.*foo.*).*\z/m

从包含bar的整个字符串的开头匹配的正则表达式是:

/\A.*bar/m

既然你想同时满足这两个,那么通过将其中一个放在前瞻中来将它们结合起来:

/\A(?=.*bar)(?!.*foo.*).*\z/m

【讨论】:

  • 完美!正是我想要的。看来当我使用多行模式时,最好分别使用\A\z 来处理字符串的开始/结束。错误是使用^$。谢谢!注意:该示例的答案内容已翻转,但在更正为 find foo, don't find bar 时它可以工作。
猜你喜欢
  • 1970-01-01
  • 2022-10-14
  • 2013-10-13
  • 2017-09-19
  • 2015-10-11
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
  • 1970-01-01
相关资源
最近更新 更多