使用正向前瞻性的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中使用的步骤会很好。有什么办法可以做到这一点吗?

使用正向前瞻性的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都要快。

您建议的两个选项并没有什么特别的问题。它们并不像正则表达式那么复杂,只要在代码中加上适当的注释,它们应该是足够容易理解的。

一般来说,我认为最好避免遍历,除非它们是必要的或极大地简化了正则表达式——它们使弄清楚发生了什么变得更加困难,因为它们向逻辑中添加了非线性元素。

不需要担心这么简单的正则表达式的相对性能,除非您正在执行大量操作或发现代码的性能问题。然而,了解不同模式的相对性能可能是有指导意义的。