正则表达式匹配一组几个可能的字符串中的一个值,但不匹配该集合中的多个字符串

时间:2016-04-27 14:57:06

标签: regex

我想要一个匹配仅包含w,x,y或z实例,但不是 w,x,y和z的任何组合的字符串的正则表达式。 " w ... w"是允许的,但不是" w ... x"或者" y ... y ... w"。

我在一些正则表达式测试网站上测试了以下内容,但我正在尝试缩短表达式的长度。有谁知道如何更简洁地表达这一点?

(^(?!.*(x|y|z)).*(w))|(^(?!.*(w|y|z)).*(x))|(^(?!.*(w|x|z)).*(y))|(^(?!.*(w|y|x)).*(z))

3 个答案:

答案 0 :(得分:3)

在否定预测中,您可以定义交替捕获组,然后检查是否存在其中一个备选项,除了之前匹配的备选项,其中包含对第一个捕获组值的反向引用的负前瞻。在PCRE正则表达式中,您可以稍后使用(?n)语法重新使用Group 1子模式。

(?i)^(?!.*(w|x|y|z).*(?!\1)(?1)).*(?1)

请参阅regex demo

(?i)会使其不区分大小写。

详细说明:

  • (?i) - 不区分大小写的修饰符
  • ^ - 字符串的开头(使用/m修饰符的行)
  • (?!.*(w|x|y|z).*(?!\1)(?1)) - 如果字符串中的wxyz位于跟随的位置,则会导致匹配失败的否定前瞻使用其中一个值但与捕获到第1组中的值不同
  • .* - 匹配并使用除换行符以外的0 +个字符(或使用/s修饰符,包括换行符)
  • (?1) - 递归第1组中使用的子模式(因此,它与编写(w|x|y|z)一样)。

答案 1 :(得分:0)

这是最快捷的方式^(?=.*([wxyz]))(?:[^wxyz]|\1)+$

 ^                    # BOS
 (?=
      .*                   # Lookahead to find
      ( [wxyz] )           # (1), Either w,x,y or z
 )
 (?:                  # Consume the string
      [^wxyz]              # Not w,x,y or z
   |                     # or,
      \1                   # Only the captured w,x,y or z allowd
 )+
 $                    # EOS

以下是其他正则表达式和此正则表达式的比较。

示例

zzzzzsadfbzzzzzzz

基准

Regex1:   (?i)^(?!.*(w|x|y|z).*(?!\1)(?1)).*(?1)
Options:  < none >
Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   1
Elapsed Time:    2.37 s,   2369.05 ms,   2369051 µs


Regex2:   ^(?=.*([wxyz]))(?:[^wxyz]|\1)+$
Options:  < none >
Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   1
Elapsed Time:    0.20 s,   204.42 ms,   204418 µs

如果我是你,我会使用效率更高的人 远离断言中不必要的复杂性。

使用非滚动循环更快^(?=.*([wxyz]))[^wxyz]*(?:\1[^wxyz]*)+$ 与多行(?m)^(?=.*([wxyz]))[^wxyz\r\n]*(?:\1[^wxyz\r\n]*)+$

相同

答案 2 :(得分:0)

您还可以使用否定前瞻来避免实例:

/^(?!(?:.*?(?:w.*[xyz]|x.*[yzw]|y.*[wxz]|z.*[wxy]).*|[^wxyz]+))(.*)$/gi

DEMO.