使用正向前瞻性的RegEx的性能和可读性
本文关键字:RegEx 性能 可读性 前瞻性 | 更新日期: 2023-09-27 18:16:18
我正在用c#中的正则表达式验证以下字符串:
[/1/2/]
[/1/2/]; [/3/4/5/]
[/1/22/333]; [/1/]; [/9999/]
基本上是一组或多组用分号分隔的方括号(但不是在末尾)。每一组由一个或多个用斜杠分隔的数字组成。不允许使用其他字符
有两种选择:
^('['/('d+'/)+'](;(?='[)|$))+$
^('['/('d+'/)+'];)*('['/('d+'/)+'])$
第一个版本使用正向向前看,第二个版本重复部分模式。
两个RegEx-es似乎都很好,做了他们应该做的事情,但读起来不太好。;)
有没有人有更好、更快、更容易阅读的解决方案?当我在试用regex101时,我意识到第二个版本使用了更多的步骤,为什么呢?
与此同时,我意识到计算c# -RegEx中使用的步骤会很好。有什么办法可以做到这一点吗?
您可以使用1个正则表达式来验证所有这些字符串:
^'[/('d+/)+'](?:;'[/('d+/)+'])*$
参见regex demo
为了更容易阅读,使用详细标志(内联(?x)
或RegexOptions.IgnorePatternWhitespace
):
var rx = @"(?x)^ # Start of string
'[/ # Literal `[/`
('d+/)+ # 1 or more sequences of 1 or more digits followed by `/`
'] # Closing `]`
(?: # A non-capturing group start
; # a semi-colon delimiter
'[/('d+/)+'] # Same as the first part of the regex
)* # 0 or more occurrences
$ # End of string
";
要测试.net正则表达式的性能(而不是步骤数),您可以使用regexhero.net服务。对于上面的3个示例字符串,我的regex显示每秒217K迭代的速度,这比您的任何一个regex都要快。
您建议的两个选项并没有什么特别的问题。它们并不像正则表达式那么复杂,只要在代码中加上适当的注释,它们应该是足够容易理解的。
一般来说,我认为最好避免遍历,除非它们是必要的或极大地简化了正则表达式——它们使弄清楚发生了什么变得更加困难,因为它们向逻辑中添加了非线性元素。
不需要担心这么简单的正则表达式的相对性能,除非您正在执行大量操作或发现代码的性能问题。然而,了解不同模式的相对性能可能是有指导意义的。