【问题标题】:Multiple words in any order using regex [duplicate]使用正则表达式以任何顺序排列多个单词[重复]
【发布时间】:2010-11-13 16:58:41
【问题描述】:

正如标题所说,我需要在一个句子中找到两个特定的单词。但它们可以是任何顺序和任何大小写。我该如何使用正则表达式来做到这一点?

例如,我需要从下面的句子中提取单词testlong,无论单词test先出现还是long出现。

This is a very long sentence used as a test

更新: 我在第一部分没有提到的是它也需要不区分大小写。

【问题讨论】:

  • 你关心单词的多次出现吗?您知道要提取哪些单词,还是要匹配符合特定模式的单词?你想知道他们在什么位置吗?
  • 我知道确切的词,不要开车关于倍数,不需要位置。我确实需要不区分大小写
  • 您使用的是哪种正则表达式? JavaScript、.NET、PHP……?性能有多重要?您是在处理非常大的字符串,还是进行大量匹配?已经发布了几个可行的答案,但没有一个特别有效。
  • 我认为最重要的事情(我今天发现)是它正在 .Net 中进行检查,所以我不确定下面的所有答案是否都适用,我已经尝试了所有但很遗憾.net 不接受任何不区分大小写的内容
  • 呃,是否区分大小写不应该依赖于正则表达式。最好将软件编程为不区分大小写。但是,要使用正则表达式以任何顺序识别多个单词,我建议在正则表达式中使用 quantifier(\b(james|jack)\b.*){2,}。与 lookaroundmode 修饰符 不同,这适用于大多数正则表达式。

标签: regex


【解决方案1】:

你可以使用

(?=.*test)(?=.*long)

来源:MySQL SELECT LIKE or REGEXP to match multiple words in one record

【讨论】:

  • 这失败了。 regex101.com/r/Z8KOLp/2
  • @ChrisJJ 提到的正则表达式不返回单词 test 或 long。但如果它以任何顺序找到单词 test 或 long 则返回匹配项,如果没有则返回不匹配项。
  • 当然,但要求是找到/提取单词,而不是简单地测试它们。
  • 另一个变体:(?is)^(?=.*\b(test)\b)(?=.*?\b(long)\b).* 它也捕获单词并匹配所有字符串。进一步锚定到^ start 这大大提高了性能。 \b 匹配一个单词边界
  • 有什么办法可以匹配这两个词中的任何一个或两个词吗?例如,如果将该正则表达式与文本 "This is a very long sentence" 一起使用,则不会找到长单词。添加一个可选的修饰符会很好。有可能吗?
【解决方案2】:

如果要提取匹配项,请使用捕获组:(test)|(long) 然后根据使用的语言,您可以使用 $1 和 $2 来引用匹配组。

【讨论】:

  • 我将此答案与下面答案中的 (?i) 结合使用,这导致了以下输出 (?i)(test(long)?) 因为事实证明我必须先测试测试再长。如果它是正确的方法是另一个故事,但它对我有用
  • 鉴于要求是匹配 test AND long,这个解决方案需要 g 标志。
【解决方案3】:

我假设(总是危险的)你想找到整个单词,所以“test”会匹配,但“testy”不会。因此该模式必须搜索字边界,所以我使用“\b”字边界模式。

/(?i)(\btest\b.*\blong\b|\blong\b.*\btest\b)/

【讨论】:

    【解决方案4】:

    不知道什么语言

     /test.*long/ 
    

    /long.*test/
    

    /test/ && /long/
    

    【讨论】:

    • 我会添加单词边界,例如/\btest\b/.
    【解决方案5】:

    试试这个:

    /(?i)(?:test.*long|long.*test)/
    

    这将匹配test 然后long,或long 然后test。它将忽略大小写差异。

    【讨论】:

    • 除非您希望它区分大小写,否则您不需要 (?i),但这有效。
    【解决方案6】:

    我在 C 中使用 libpcre,我可以在其中定义标注。它们不仅帮助我轻松匹配单词,还帮助我轻松匹配任何顺序的任何子表达式。正则表达式看起来像:

    (?C0)(expr1(?C1)|expr2(?C2)|...|exprn(?Cn)){n}
    

    并且标注函数保护每个子表达式只匹配一次,例如:

    int mycallout(pcre_callout_block *b){
    static int subexpr[255];
    if(b->callout_number == 0){
        //callout (?C0) - clear all counts to 0
        memset(&subexpr,'\0',sizeof(subexpr));
        return 0;
    }else{
        //if returns >0, match fails
        return subexpr[b->callout_number-1]++;
    }
    }
    

    类似的东西在 perl 中也应该是可能的。

    【讨论】:

      【解决方案7】:

      Vim 有一个分支运算符 \&,它允许在搜索包含任意数量的单词的行时使用更简洁的正则表达式。

      例如,

      /.*test\&.*long

      将匹配包含testlong 的行,顺序不限。

      有关使用的更多信息,请参阅this answer。我不知道任何其他实现分支的正则表达式风格;该操作员甚至没有记录在 Regular Expression 维基百科条目中。

      【讨论】:

        【解决方案8】:

        我不认为你可以用一个正则表达式来做到这一点。您需要对两个进行逻辑与 - 一个搜索每个单词。

        【讨论】:

          猜你喜欢
          • 2014-12-06
          • 1970-01-01
          • 2011-12-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-18
          • 1970-01-01
          • 2013-12-15
          相关资源
          最近更新 更多