SonarLint 目前因为我用于税号的一些正则表达式的复杂性而对我大喊大叫。我需要将复杂性从 21 降低到 20,但我实在想不出办法来做到这一点。我尝试过的所有解决方案只会让它变得更加复杂......
有问题的正则表达式:
^\d{9}$|^\d{3}-\d{2}-\d{4}$|^\d{2}-\d{7}$|^\d{3}-\d{3}-\d{3}$
需要匹配这些特定格式的税号,仅此而已:
555555555
555-55-5555
55-5555555
555-555-555
Sonar 对正则表达式复杂性的讨论 建议考虑用常规代码替换正则表达式(我推断在某些情况下可能涉及更简单的正则表达式)。在这里,通过单独的正则表达式测试每个替代方案而不是将它们全部塞进一个,看起来很简单,所以请考虑一下。
同样的讨论描述了声纳如何计算正则表达式的复杂性:
以下每个运算符都会增加一个数量的复杂性 等于当前的嵌套级别,也增加了当前 逐层嵌套其参数:
- 的复杂度
- 当多个 |运算符一起使用,后面的只会增加1|
(字符类内部) - 当多个&&
运算符一起使用时,后续运算符只会增加复杂度 1&&
- 量词(
、*
、+
、?
、{n,m}
或{n,}
){n}
- 设置标志的非捕获组(例如
或(?i:some_pattern)
)(?i)some_pattern
- 前瞻和后视断言
此外,每次使用以下功能都会增加 无论嵌套如何,复杂度增加 1:
- 字符类
- 反向参考
生成 21 到 9 个量词,每个都在嵌套级别 2,加上三个
|
运算符,都在嵌套级别 1:2 * 9 + 3 == 21.
我怀疑这项工作是否存在一个不太复杂的正则表达式,尤其是实现此 Sonar 规则精神的正则表达式:使正则表达式用法易于阅读和维护。但是,您仍然可以通过以下方式让 Sonar 无怨无悔地接受它:
如果正则表达式在多个变量之间拆分,则 复杂性是针对每个变量单独计算的,而不是针对 整个正则表达式。如果正则表达式被拆分 多行,如果伴随每行单独处理 通过注释(Java 注释或常规注释中的注释 表达式),否则将正则表达式作为一个整体进行分析。
我认为这意味着 Sonar 可以接受以下内容:
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}$"
);
文档让我相信,沿着类似的方式分别表达正则表达式片段,会有其他可行的变体。