【问题标题】:Match a string between two or more words regardless of order匹配两个或多个单词之间的字符串,无论顺序如何
【发布时间】:2020-09-01 08:05:11
【问题描述】:

我需要一个匹配单词的正则表达式,无论顺序如何。例如,这些行应该与标记的范围相匹配,

A longword1 B longword2 C
  ^-------------------^

A longword2 B longword1 C
  ^-------------------^

虽然这些不应该:

A longword1 B longword1 C
A longword2 B longword2 C
A longword1 B
A longword2 C

(A、B、C 是填充符,基本上可以是任何文本)

可以只使用替换,例如:\b((longword1).*?(longword2)|(longword2).*?(longword2))\b。但是正则表达式会阶乘增长,即三个单词需要 3!替补。也可以使用子程序,例如\b((?'A'longword1).*?(?'B'longword2')|(?P>B).*?(?P>A))\b。虽然更短,但我仍然需要包含它的所有排列。

现在我已经阅读了this postthis other one,但接受的答案并不能完全解决我的问题。使用\b(?=.*longword1)(?=.*longword2).*\b 将匹配整行而不是我显示的范围。

我明白,如果我对照单词列表检查句子会容易得多。但是我当前的用例阻止了它的实现;我只能使用正则表达式。

这里有一些链接来说明我的意思:

预期:

不正确:

有没有更简单的正则表达式来解决这个问题?

【问题讨论】:

  • AC 放在其他帖子中的解决方案周围。
  • @Barmar 我找不到您提到的解决方案。什么意思?
  • A.*\b(?=.*longword1)(?=.*longword2).*\b.*C
  • @Barmar 但它匹配从AC。 OP 只需要匹配从 word1 到 word2 的子字符串。 AC 只是填充物,它们表示任何文本。并且单词 1 和单词 2 可以互换。而且可以有两个以上的词。

标签: regex pcre


【解决方案1】:

您可以使用反向引用 + 子程序:

\b(longword1|longword2)\b.*?\b(?!\1\b)(?1)\b

将其扩展为三种选择:

\b(longword1|longword2|longword3)\b.*?\b(?!\1\b)((?1))\b.*?\b(?!(?:\1|\2)\b)(?1)\b

也可以查看regex demothis regex demo。因此,单词列表将在第 1 组中,您只需在后续子例程之前添加反向引用即可。

详情

  • \b(longword1|longword2)\b - 一个完整的单词,longword1longword2
  • .*? - 除换行符之外的任何 0 个或多个字符,尽可能少
  • \b - 单词边界
  • (?!\1\b) - 第 1 组中的匹配文本不能与后跟单词边界的文本相同
  • (?1) - 与第 1 组中的相同模式匹配的子例程
  • \b - 单词边界

【讨论】:

  • 只是好奇,这种语法会严重影响正则表达式的性能吗?
  • @NickyLogan 当然会。但是交替会导致更多的回溯。
  • 太棒了!我以为我非常了解正则表达式,但是当我坚持这样的任务并找到您的解决方案时,我明白我不知道。谢谢!
猜你喜欢
  • 2015-04-08
  • 2017-04-02
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 2013-10-16
  • 2019-02-08
  • 2019-04-04
  • 2019-01-12
相关资源
最近更新 更多