regex 简化此正则表达式以降低其复杂性

hgqdbh6s  于 2023-04-07  发布在  其他
关注(0)|答案(1)|浏览(114)

SonarLint目前正在对我大喊大叫,因为我正在使用的一些正则表达式的复杂性为税务ID号码.我需要减少复杂性从21到20,我根本想不出一种方法来做到这一点.我已经尝试过的所有解决方案只会使它更复杂...
问题中的正则表达式:

^\d{9}$|^\d{3}-\d{2}-\d{4}$|^\d{2}-\d{7}$|^\d{3}-\d{3}-\d{3}$

它需要匹配这些特定格式的纳税ID号,除此之外什么都不需要:
555555555
555-55-5555
55-5555555
555-555-555

svmlkihl

svmlkihl1#

Sonar's discussion of regex complexity建议考虑用常规代码替换正则表达式(我推断在某些情况下可能会涉及更简单的正则表达式)。在这里,看起来通过单独的正则表达式测试每个替代方案而不是将它们全部塞进一个,这样做会很简单,所以请考虑一下。
同样的讨论描述了Sonar如何计算正则表达式复杂度:
以下每个运算符都会将复杂度增加等于当前嵌套级别的量,并且还会将其参数的当前嵌套级别增加1:

  • |-当多个|运算符一起使用时,后续运算符的复杂度仅增加1
  • &&(字符类内部)-当多个&&运算符一起使用时,后续运算符的复杂度仅增加1
  • 量词(*+?{n,m}{n,}{n}
  • 设置标志的非捕获组(如(?i:some_pattern)(?i)some_pattern
  • 先行和后看Assert

此外,无论是否嵌套,每次使用以下功能都会使复杂度增加1:

  • 字符类
  • 反向引用

这将产生21到9个量词,每个量词位于嵌套级别2,加上三个|运算符,所有运算符都位于嵌套级别1:2 * 9 + 3 == 21。
我怀疑是否存在一个不那么复杂的正则表达式来完成这项工作,特别是一个能够实现Sonar规则精神的正则表达式:使regex用法易于阅读和维护。然而,您仍然可以通过利用以下内容让Sonar毫无怨言地接受它:
如果一个正则表达式被拆分成多个变量,那么复杂度是针对每个变量单独计算的,而不是针对整个正则表达式。如果一个正则表达式被拆分成多行,那么如果每行都带有注解(Java注解或正则表达式中的注解),那么每一行都会被单独处理,否则正则表达式会作为一个整体进行分析。
我认为这意味着声纳可以接受以下内容:

Pattern p = Pattern.compile(
            // xxxxxxxxx
            "^\d{9}$"
            // xxx-xx-xxxx
            + "|^\d{3}-\d{2}-\d{4}$"
            // xx-xxxxxxx
            + "|^\d{2}-\d{7}$"
            // xxx-xxx-xxx
            + "|^\d{3}-\d{3}-\d{3}$"
            );

这些文档让我相信,沿着类似的路线,还会有其他可行的变体分别表达正则表达式。

相关问题