【问题标题】:Regex - match if at least 2 words out of N words, in any order正则表达式 - 如果 N 个单词中至少有 2 个单词以任意顺序匹配
【发布时间】:2018-02-13 02:04:47
【问题描述】:

我正在尝试创建一个正则表达式,如果一个字符串在 N 中至少包含 2 个单词,则该表达式将创建一个匹配项。例如,取单词 ('one', 'two', 'three', 'four ')。此正则表达式应返回所有这些情况的匹配项:

one two three four
twothreeone
two plus two is four

它不应该返回匹配项:

one
three plus three is three

我尝试过类似 this'/^(?=.*one)(?=.*two)(?=.*three)(?=.*four).+/' 的方法,但只有当字符串中包含所有单词 ('one', 'two', 'three', 'four') 时才会匹配。

【问题讨论】:

  • 您可以执行以下操作:(one|two|three|four).*(?!\1)(?:one|two|three|four),但使用基本字符串函数测试每个单词并在获得两个结果后停止会更简单。
  • 这是我想出的解决方案之一,但实际上我还有很多字(大约 30 个)需要检查,所以我希望得到一些不需要我输入的字词一切都两次。
  • 在 Perl/PCRE 中,您可以使用 (?n) 对捕获组中的子模式的引用,其中 n 是捕获组的编号。所以:(one|two|three|four).*(?!\1)(?1)。在最坏的情况下,当您知道快捷键 ctrl+c 和 ctrl+v 时,您不必键入两次
  • @CasimiretHippolyte,它有效!很好的发现,每天都学习新东西!确实,PCRE 不需要复制粘贴!

标签: regex regex-lookarounds


【解决方案1】:

为窃取某人的评论道歉,但它似乎确实有效!

在 Perl/PCRE 中,您可以使用 (?n) 对捕获组中的子模式的引用,其中 n 是捕获组的编号。所以:(一|二|三|四).*(?!\1)(?1)。在最坏的情况下,当您知道快捷键 ctrl+c 和 ctrl+v 时,您不必输入两次 – Casimir et Hippolyte 4 小时前

% pcretest 
PCRE version 8.35 2014-04-04

  re> #(one|two|three|four).*(?!\1)(?1)#
data> one one one
No match
data> one two one
 0: one two
 1: one
data> one four
 0: one four
 1: one
data> four four
No match
data> ^D
%

确实,在pcre,这是nginx(OpenBSD 端口中整个 nginx 端口的唯一依赖项!)和许多其他软件使用的一个流行库,您可以使用类似(?1)(或(?-1)) 引用之前的模式,因此,您不必多次复制粘贴该东西,以及负前瞻,这只是标准票价。

这里是有关相关功能的文档 - 您可能需要查看 pcrepatternpcresyntax 手册页,如下所示:

等等

一般来说,http://www.pcre.org/original/pcre.txthttp://www.pcre.org/pcre2.txt 页面包含完整的文档,有助于搜索您在某处看到的语法。

【讨论】:

  • “为窃取某人的评论道歉”:没问题,我有空写一个答案。
【解决方案2】:
(one|two|three|four).*(?!\1)(?-1)

解释:

  • 捕获组中的一个单词
  • 查找任意数量的字符
  • 如果您发现最后一组匹配的内容不匹配
  • 除非您在该组后面找到另一组匹配项(递归子模式)

这意味着当您编辑它时,您将能够只编辑一个捕获组,假设您使用的是 PCRE 正则表达式(比如 PHP)。

查看demo

【讨论】:

  • 请注意,如果您同时对同一组使用绝对反向引用\1,则使用对子模式(?-1) 的相对引用是没有意义的。简而言之,写(one|two|three|four).*(?!\1)(?1)(one|two|three|four).*(?!\g{-1})(?-1) 但不要写(one|two|three|four).*(?!\1)(?-1)(one|two|three|four).*(?!\g{-1})(?1)
【解决方案3】:

搜索目标词的两个副本,但捕获第一个并使用对第一个组的反向引用对第二个词应用否定前瞻,以断言第二个词出现了不同词小组 - 总共(至少)2个。

(one|two|three|four).*(?!\1)(one|two|three|four)

live demo

【讨论】:

    猜你喜欢
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多