问题描述
我需要一个与单词无关的正则表达式。例如,这些行应与标记的范围匹配,
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 post和this other one,但是被接受的答案并不能完全解决我的问题。使用\b(?=.*longword1)(?=.*longword2).*\b
会匹配整行而不是我显示的范围。
我知道,如果我根据单词列表检查句子,会容易得多。但是我当前的用例阻止了它的实现。我只能使用正则表达式。
这里有一些链接可以证明我的意思:
已执行:
- 使用替代项:https://regexr.com/5b6pv
- 使用子例程:https://regexr.com/5b6ss
错误:
- 使用积极的前瞻性(链接):https://regexr.com/5b6q2
有没有更简单的正则表达式来解决这个问题?
解决方法
您可以使用反向引用+子例程:
\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 demo和this regex demo。因此,单词列表将在第1组中,并且您只需要在后续子例程之前添加反向引用即可。
详细信息
-
\b(longword1|longword2)\b
-整个单词,longword1
或longword2
-
.*?
-除换行符以外的任何0个或多个字符,应尽可能少 -
\b
-单词边界 -
(?!\1\b)
-不能有与第1组匹配的相同文本,后接单词边界 -
(?1)
-与第1组中的模式相同的子程序 -
\b
-单词边界