如果字符串中的多个选项中只有一个匹配项,则正则表达式匹配

Regex match if there is only one match from a number of choices in a string

是否有一种模式可以判断一个字符串中的多个选项是否只有一个匹配项?

假设我们有以下潜在匹配列表:

`foo|bar|baz`

我们有字符串:

`Foo bar, Cambaz!` // shoud not match due to multiple findings
`My bar, good!` // shoud match for `bar`
`My friend, Cambaz!` // shoud match for baz

不区分大小写。

您可以使用这个 PCRE 正则表达式:

^(?>.*?(foo|bar|baz)){2}.*(*SKIP)(*F)|(?1)

RegEx Demo

  • (*F)(*FAIL) 动词的行为类似于失败的否定断言,并且是 (?!)
  • 的同义词
  • (*SKIP) 定义了一个点,当子模式稍后失败时,正则表达式引擎不允许回溯超过该点
  • (*SKIP)(*FAIL) 技巧的想法是消耗您想要避免的字符,并且不能是匹配结果的一部分。
  • (?1): 递归第一个子模式

使用

(?i)^(?:(?!foo|bar|baz).)*\K(?:foo|bar|baz)(?!.*(?:foo|bar|baz))

proof

匹配一些不匹配任何替代项的文本,直到第一个匹配项 (^(?:(?!foo|bar|baz).)*),省略匹配的文本 (\K),匹配列表中的单词 ((?:foo|bar|baz)), 然后检查文本后面的列表中没有单词 ((?!.*(?:foo|bar|baz))).

(?i) - 不区分大小写。

带子程序的缩短版:

(?i)^(?:(?!(foo|bar|baz)).)*\K\g<1>(?!.*\g<1>)

another proof

\g<1>代表(foo|bar|baz)模式。

您还可以使用 (*COMMIT) 在(此处为前瞻)之后的子模式失败时中止进一步研究:

(foo|bar|baz)(*COMMIT)(?!.*(?1))

demo