正则表达式负提前查找问题确保仅在第一组中没有重复字符

时间:2019-07-15 20:53:02

标签: regex

我正在尝试以负的超前性编写正则表达式,并且似乎遇到了一个较小的语法问题。

我要匹配以下格式: DayOfWeek-24HourTimeFormat-Number [1-99]

示例: MTWRFSU-23:00-02
M-23:00-02
MT-23:00-02

我不希望星期几(第一个连字符之前)有重复的字母,并且只能是以下其中之一:MTWRFSU

以下正则表达式仅匹配示例的最后一个字母

((?!=.*(.).*\1)[MTWRF])-([01]?[0-9]|2[0-3]):[0-5][0-9]-([1-9]|[1-9]|[1-9][0-9])

例如MT-23:00-2仅与T-23:00-2匹配

这可能很简单。谁能告诉我我所缺少的内容,或者是否有更好的方法来做到这一点?预先感谢!

((?!=.*(.).*\1)[MTWRF])-([01]?[0-9]|2[0-3]):[0-5][0-9]-([1-9]|[1-9]|[1-9][0-9])

我期待
MT-23:00-02(MATCH)
MTT-23:00-02(失败,因为重复了T)

2 个答案:

答案 0 :(得分:1)

在这种情况下,最快的方法就是这样。
在这里,只关注字母部分。

(?m)^(?:(?>(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU]))){1,7}$

https://regex101.com/r/gBaBYw/1

扩展

 (?m)    
 ^ 
 (?:   
    (?>
        (?!\1|\2|\3|\4|\5|\6)( [MTWRFSU] )
      | (?!\1|\2|\3|\4|\5|\6)( [MTWRFSU] )
      | (?!\1|\2|\3|\4|\5|\6)( [MTWRFSU] )
      | (?!\1|\2|\3|\4|\5|\6)( [MTWRFSU] )
      | (?!\1|\2|\3|\4|\5|\6)( [MTWRFSU] )
      | (?!\1|\2|\3|\4|\5|\6)( [MTWRFSU] )
      | (?!\1|\2|\3|\4|\5|\6)( [MTWRFSU] )
    )
 ){1,7}
 $ 

我们可以通过基准比较本页上显示的正则表达式,
该正则表达式为#1,而Stribnetz改进的正则表达式为#2,而Stribnetz
原始正则表达式是#3。

通常,在这种正则表达式中,速度越快越好!

Regex1:   (?m)^(?:(?>(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU])|(?!\1|\2|\3|\4|\5|\6)([MTWRFSU]))){1,7}$
Completed iterations:   5  /  5     ( x 1000 )
Matches found per iteration:   9
Elapsed Time:    0.63 s,   627.27 ms,   627275 µs
Matches per sec:   71,738


Regex2:   (?m)^(?![MTWRFSU]*([MTWRFSU])[MTWRFSU]*\1)[MTWRFSU]+$
Completed iterations:   5  /  5     ( x 1000 )
Matches found per iteration:   9
Elapsed Time:    0.66 s,   664.90 ms,   664896 µs
Matches per sec:   67,679


Regex3:   (?m)^(?![A-Z]*([MTWRFSU])[A-Z]*\1)[MTWRFSU]+$
Completed iterations:   5  /  5     ( x 1000 )
Matches found per iteration:   9
Elapsed Time:    0.84 s,   837.94 ms,   837943 µs
Matches per sec:   53,702

答案 1 :(得分:0)

请注意,(?!=.*(.).*\1)前瞻将无法匹配您在任何重复字符(甚至连字符或空格)的字符串。

您需要使用类似的

^(?![A-Z]*([MTWRFSU])[A-Z]*\1)([MTWRFSU]+)-([01]?[0-9]|2[0-3]):[0-5][0-9]-(0?[1-9]|[1-9][0-9])$

请参见regex demo

详细信息

  • ^-字符串的开头
  • (?![A-Z]*([MTWRFSU])[A-Z]*\1)-不再重复MTWRFS,{{1 }}用0个或多个大写字母分隔,并且仅在0个或多个大写字母之后
  • U-第1组:([MTWRFSU]+)MTWRF或{{ 1}}
  • S-连字符
  • U-组2:-([01]?[0-9]|2[0-3])(可选),然后是任意数字或01
  • 20-冒号
  • 23-:[0-5][0-9]
  • 00-连字符
  • 59-第3组:可选的-,然后是从(0?[1-9]|[1-9][0-9])019的数字。
  • 10-字符串的结尾。