【问题标题】:PCRE match when words but exclude a list of words within or in relation to matching words当单词匹配但排除匹配单词内或与之相关的单词列表时,PCRE 匹配
【发布时间】:2016-12-30 13:06:59
【问题描述】:

我正在尝试使用 PCRE 正则表达式来匹配以下单词列表:

  1. 牛奶
  2. 鸡蛋

以下字符串:

milk, goatmilk, goat milk, cow milk, watch out for ( milk, eggs), egg, cornstarch
milk. goatmilk. goat milk. cow milk. watch out for ( milk, eggs). egg. cornstarch
milk goatmilk goat milk cow milk watch out for ( milk, eggs). egg cornstarch

这将是一个简单的练习,但遗憾的是它无法匹配以下任何单词:

  • 羊奶
  • 山羊奶

在上述情况下,字符串应该匹配,因为单词:

  • 牛奶
  • 鸡蛋
  • 鸡蛋

但如果字符串中不包含任何这些词则不应该匹配,即:

sugar, wheat, goatmilk, goat milk, cornstarch

我尝试过应用这些但没有任何成功:

我从上述资源中得到的最接近的正则表达式是:

\b(?!(?:goatmilk|goat\smilk))(egg|milk)\b

这仍然会匹配所有单词牛奶,更糟糕的是它会因为单词边界而跳过单词鸡蛋。如果我删除边界这个词,它也会匹配 goatmilk..

我已经想到了使用两个正则表达式的可能性,一个匹配所有单词,另一个检查匹配单词中的排除单词。然而;如果不是山羊和牛奶之间的空间,这将非常有效,因为山羊部分不会在比赛中。

如果没有选项,我将使用 PHP 在空间上展开,遍历数组,如果找到匹配项,将检查先前的索引值以查看组合是否包含要排除的单词缓解空间问题。然而;我宁愿不使用它,因为我认为这个选项很丑:(

【问题讨论】:

标签: php regex pcre


【解决方案1】:

如果您必须避免返回属于goatmilkgoat milkmilk,您可以使用(*SKIP)(*FAIL) regex

\bgoat\s*milk\b(*SKIP)(*FAIL)|\b(?:eggs?|milk)\b

regex demo

\bgoat\s*milk\b(*SKIP)(*FAIL) 分支将匹配 goatmilkgoat milk 并由于这 2 个 PCRE 动词而丢弃匹配项。 \b(?:eggs?|milk)\b 分支将返回其他 eggeggsmilk 匹配作为整个单词。

【讨论】:

  • 我已将正则表达式更改为: \b(goatmilk|goat\smilk)\b(*SKIP)(*FAIL)|(egg|milk) 现在它也将匹配鸡蛋。我可以简单地添加到 SKIP/FAIL 列表中的任何其他词。我需要分析所有数据以获得最佳正则表达式,但这很棒!
  • 由于s? - 1 或 0 segg 之后,我的模式也将作为一个整体匹配eggs。无论如何,欢迎您进一步自定义。
  • 这是正确的,但这个正则表达式将是动态的,因此会删除 s?会让事情变得更容易:)
猜你喜欢
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-23
相关资源
最近更新 更多