【问题标题】:Regex for finding words with no or only one word between them用于查找它们之间没有或只有一个单词的单词的正则表达式
【发布时间】:2016-11-09 13:56:56
【问题描述】:

我需要在多个字符串中找到两个没有单词或它们之间只有一个单词的单词。我为该案例创建了正则表达式,以查找这两个单词是否存在于字符串中:

^(?=[\s\S]*\bFirst\b)(?=[\s\S]*\bSecond\b)[\s\S]+

它可以正常工作。 然后我尝试在这个正则表达式中插入附加代码:

^(?=[\s\S]*\bFirst\b)(\b\w+\b){0,1}(?=[\s\S]*\bSecond\b)[\s\S]+

但它没有用。它选择在搜索词之间具有两个或多个词的文本。这不是我需要的。 第一第二 - 必须选择 第一个词1 第二个 - 必须选择 第一个 word1 word2 第二个 - 不能由正则表达式选择,但我的正则表达式选择它。

我能得到建议如何解决这个问题吗?

【问题讨论】:

  • 也许,^(?=[\s\S]*\bFirst(?:\W+\w+)?\W+Second\b)[\s\S]+?还是你还需要匹配Second FirstSecond word First
  • 另外,检查^(?=[\s\S]*\b(First|Second)(?:\W+\w+)?\W+(?!\1\b)(?:First|Second)\b)[\s\S]+
  • 是的,我需要选择“第二优先”和“第二单词优先”。您的两个示例都可以正常工作。谢谢。
  • 如果您的要求不符合问题,请更新问题并添加应该匹配和不应该匹配的示例文本。

标签: regex


【解决方案1】:

根本原因

您应该记住,环视匹配字符串而不沿字符串移动,它们是"stand their ground"。写完^(?=[\s\S]*\bFirst\b)(\b\w+\b){0,1}(?=[\s\S]*\bSecond\b),执行如下:

  • ^ - 正则表达式引擎检查当前位置是否是字符串的开头
  • (?=[\s\S]*\bFirst\b) - 积极的前瞻要求存在任何 0+ 字符,后跟一个完整的单词 First - 请注意,在前瞻返回 true 后,正则表达式索引仍位于字符串的开头或错误
  • (\b\w+\b){0,1} - 只有当上述检查为 true(即某处有一个完整的单词 First)并且匹配(使用、移动正则表达式索引)出现 1 次或 0 次时,才会检查此子模式整个单词(即字符串开头必须有 1 个或多个单词字符
  • (?=[\s\S]*\bSecond\b) - 另一个积极的前瞻,确保在\b\w+\b 使用的第一个完整单词之后的某个地方有一个完整的单词Second - 如果有的话。即使单词Second 是字符串中的第一个单词,这也会返回true,因为回溯将退回与(\b\w+\b){0,1} 匹配的单词(请参阅,它是可选的),并且Second 将被断言,并且@ 987654336@ 将抓取整个字符串(第 1 组将为空)。见the regex demo with Second word word2 First string

因此,您的方法不能保证 FirstSecond 在字符串中的顺序,它们只需要存在,但不一定按照您期望的顺序。

解决方案

如果您需要检查字符串中FirstSecond 的顺序,则需要将所有检查合并为一个前瞻。 对于较长的字符串和环顾中的多个替代方案,该方法可能会变得非常低效,请考虑展开模式或尝试多个正则表达式模式(如此伪代码if /\bFirst\b/.finds_match().index < /\bSecond\b/.finds_match().index => Good, go on...)。

如果您打算继续使用正则表达式方法,则可以仅按以下顺序匹配包含 First....Second 的字符串:

^(?=[\s\S]*\bFirst(?:\W+\w+)?\W+Second\b)[\s\S]+

regex demo

详情

  • ^ - 字符串开头
  • (?=[\s\S]*\bFirst(?:\W+\w+)?\W+Second\b) - 必须有:
    • [\s\S]* - 任何零个或多个字符,直到最后一个
    • \bFirst - 整个词 First
    • (?:\W+\w+)? - 1+ 非单词字符和 1+ 单词字符的可选序列(1 或 0 次出现)
    • \W+ - 1+ 非单词字符
    • Second\b - Second 整体而言
  • [\s\S]+ - 任意 1 个或多个字符(空字符串不匹配)。

【讨论】:

  • 是的,它有效,但对我来说有一些问题。此搜索是以某种顺序搜索单词 - 首先,我不需要查找不按此顺序的组合。单词的数量可以超过2个。可以是:First Second Third asn等等。一切按顺序。所以对于正则表达式模式的形成,我使用可以形成的循环:
  • 这是否意味着第一个 ^(?=[\s\S]*\bFirst(?:\W+\w+)?\W+Second\b)[\s\S]+ 正则表达式适合您?您只需要将限制量词调整为^(?=[\s\S]*\bFirst(?:\W+\w+){2,}\W+Second\b)[\s\S]+? {2,} 表示 2 个或更多,如果 FirstSecond 之间的单词较少,则不匹配。
  • 是的,它有效,但不完全是我需要的。此搜索以某种顺序搜索单词 - First Second。我不需要找到不按此顺序的组合。单词的数量可以超过2个。可以是:First Second Third等。因此,对于正则表达式模式的形成,我使用可以形成的循环 - ^(?=[\s\S]*\bFirst\b)(?=[\s\S]*\bSecond\b)[\s\S]+和更多单词的模式。我需要正则表达式的 sn-p,它只估计一个单词,我可以在 (?=[\s\S]*\bFirst\b) 和 (?=[\s\S]*\bSecond\b) 和在其他词之间搜索它们是否将被包括在内。有可能吗?
  • 我会更新答案,但同时,如果您想要一个完整的解决方案,请发布您用于构建动态模式的代码。
  • 我搜索的单词之间必须没有或只有一个单词。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 2017-02-03
  • 2020-05-09
  • 1970-01-01
相关资源
最近更新 更多