【问题标题】:Regex multi word search正则表达式多词搜索
【发布时间】:2008-10-16 22:26:09
【问题描述】:

如何在一个字符串中搜索多个单词?我希望逻辑运算为 AND,以便所有单词都在字符串中的某个位置。我有一堆废话段落和一个简单的英文段落,我想通过指定几个常用词来缩小范围,例如“the”和“and”,但希望它与我指定的所有词匹配。

【问题讨论】:

    标签: regex string


    【解决方案1】:

    正则表达式支持“环视”条件,可让您在字符串中搜索术语,然后忘记结果的位置;从下一个搜索词的字符串开头开始。这将允许以任何顺序在字符串中搜索一组单词。

    这个的正则表达式是:

    ^(?=.*\bword1\b)(?=.*\bword2\b)(?=.*\bword3\b)
    

    其中\b 是单词边界,?= 是环视修饰符。

    如果要搜索的单词数量不定,则需要使用循环构建此正则表达式字符串 - 只需将每个单词包装在环视语法中并将其附加到表达式中。

    【讨论】:

    • 正是我需要的。请注意,上面缺少几个星号。每个部分应为(?=.*\bword\b)
    • 星号在那里,但它们被视为标记。我通过应用代码格式来修复它。
    【解决方案2】:

    AND 串联

    ^(?=.*?\b(?:word1)\b)(?=.*?\b(?:word2)\b)(?=.*?\b(?:word3)\b)
    

    OR 作为替代

    ^(?=.*?\b(?:word1|word2|word3)\b
    ^(?=.*?\b(?:word1)\b)|^(?=.*?\b(?:word2)\b)|^(?=.*?\b(?:word3)\b)
    

    【讨论】:

      【解决方案3】:

      也许使用language recognition chart 来识别英语会起作用。一些快速测试似乎有效(假设段落仅由换行符分隔)。

      正则表达式将匹配其中任何一个条件... \bword\b 是由边界分隔的单词 word\b 是一个单词结尾,并且仅 word 将在要匹配的段落的任何位置匹配它。

      my @paragraphs = split(/\n/,$text);
      for my $p (@paragraphs) {
          if ($p =~ m/\bthe\b|\band\b|\ban\b|\bin\b|\bon\b|\bthat\b|\bis\b|\bare\b|th|sh|ough|augh|ing\b|tion\b|ed\b|age\b|’s\b|’ve\b|n’t\b|’d\b/) {
             print "Probable english\n$p\n";
          }
      }
      

      【讨论】:

      • 我不建议使用 'on' 来检测英语。在许多斯拉夫语言中,这意味着“他”(我相信 Vinko 知道;)
      • 网址已移动:en.wikipedia.org/wiki/…
      【解决方案4】:

      首先,我不确定您要返回什么...整个句子?两个给定词之间的词?

      类似:

      \b(word1|word2)\b(\w+\b)*(word1|word2)\b(\w+\b)*\.
      

      (其中\b 是您的语言中的单词边界) 将匹配包含两个单词中的一个或两者的完整句子..

      你可能需要让它不区分大小写,这样如果它出现在句子的开头,它仍然会匹配

      【讨论】:

      • 不只匹配包含两个单词的句子,或者 word1 后跟 word2,或者 word2 后跟 word1(根据需要),或者 word1 后跟 word1,或者 word2 后跟 word2(如不需要)?这就是我在尝试回答时遇到的那种问题。
      【解决方案5】:

      假设 PCRE(Perl 正则表达式),我不确定您是否可以轻松做到这一点。 AND 操作是正则表达式的串联,但您希望能够排列单词出现的顺序,而不必正式生成排列。对于N个词,当N=2时,是可以忍受的; N = 3,勉强可以;当 N > 3 时,它不太可能被接受。因此,简单的迭代解决方案 - N 个正则表达式,每个单词一个,并迭代确保每个都满足 - 对我来说似乎是最佳选择。

      【讨论】:

      • 为什么 N 个东西必须是正则表达式?可以在这里使用“索引”。
      • \b(foo|bar|baz)\b.*\b(?!\1)(foo|bar|baz)\b.*\b(?!\1)(? !\2)(foo|bar|baz)\b 应该通过使用反向引用和负前瞻来处理排列,以避免匹配一个单词两次。它仍然是邪恶的,但至少模式长度不是 O(N!)
      • @BKB:我不确定你所说的使用索引是什么意思。
      • @SteveMegson:是的,我想我明白你在做什么——并且不确定负前瞻的范围(Perl 的一个相对较新的特性——因为我真的在学习它,回来在 4.x 和 5.[0-6]) 时代,我的回答并不教条。正如你所说,不好,但也不是组合的。
      猜你喜欢
      • 1970-01-01
      • 2011-10-13
      • 2022-12-05
      • 2020-01-25
      • 2012-03-10
      • 2012-02-23
      • 1970-01-01
      • 2017-01-09
      • 2015-03-16
      相关资源
      最近更新 更多