顺便说一句:我不会使用前瞻解决方案。
如果有很多逗号,前瞻将具有相对于逗号数量的对数延迟。
原因是像这样使用的前瞻可以是开放式的。如果有可能没有任何东西来终止前瞻,那么这不是一个好主意。特别是在大量数据的情况下。
每次正则表达式找到一个逗号,它都要执行这个操作 (?![^()]*\))
它的作用是向前查看直到找到括号为止。这意味着它也会匹配逗号。
如果您有一个字符串像这样asdf,asdf,asdf,aasdf,aaaasdf,asdf,aasdf,asdf
,则进展如下:
第一组匹配:找到,
,并在所有的asdf,asdf,aasdf,aaaasdf,asdf,aasdf,asdf
中向前查看。
第二组匹配:找到,
,并在所有的asdf,aasdf,aaaasdf,asdf,aasdf,asdf
中向前查看。
第三组匹配:找到,
,并在所有的aasdf,aaaasdf,asdf,aasdf,asdf
中向前查看。
第四组匹配:找到,
,并在所有的aaaasdf,asdf,aasdf,asdf
中向前查看。
第五组匹配:找到,
,并在所有的asdf,aasdf,asdf
中向前查看。
第六组匹配:找到,
,并在所有的aasdf,asdf
中向前查看。
第七组匹配:找到,
,并在所有的asdf
中向前查看。
这是一个很小的字符串,却匹配了那么多东西。
不要像这样使用正则表达式进行拆分或任何类型的匹配。
我只需要在全局查找中匹配字段值。
"(?:\\A|\\G,\\s*)([^(),]*(?:(?:\\([^()]*\\))[^(),]*)*)"
这里有一个简单的基准测试,展示了使用类似这样的前瞻性可以引起的延迟:
示例:260个字符,42个逗号
asdf,asdf,asdf,asdf,asdf,asdf,asdf,
asdf,asdf,asdf,asdf,asdf,asdf,asdf,
asdf,asdf,asdf,asdf,asdf,asdf,asdf,
asdf,asdf,asdf,asdf,asdf,asdf,asdf,
asdf,asdf,asdf,asdf,asdf,asdf,asdf,
asdf,asdf,asdf,asdf,asdf,asdf,asdf,
asdf,asdf,asdf,asdf,asdf,asdf,asdf,
基准测试
Regex1: (?:\A|\G,\s*)([^(),]*(?:(?:\([^()]*\))[^(),]*)*)
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 50
Elapsed Time: 2.97 s, 2972.45 ms, 2972454 µs
Regex2: ,(?![^()]*\))\s*
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 49
Elapsed Time: 21.59 s, 21586.81 ms, 21586811 µs
当样本加倍时,时间变得更糟糕。
Regex1: (?:\A|\G,\s*)([^(),]*(?:(?:\([^()]*\))[^(),]*)*)
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 99
Elapsed Time: 5.89 s, 5887.16 ms, 5887163 µs
Regex2: ,(?![^()]*\))\s*
Options: < none >
Completed iterations: 50 / 50 ( x 1000 )
Matches found per iteration: 98
Elapsed Time: 83.06 s, 83063.77 ms, 83063772 µs