按逗号分隔字符串,而不考虑括号中的逗号

3

我有一个字符串例如

s="abc, 3rncd (23uh, sdfuh), 32h(q23q)89 (as), dwe8h, edt (1,wer,345,rtz,tr t), nope";

我想把它分成几个字符串

String[] parts={"abc", "3rncd (23uh, sdfuh)", "32h(q23q)89 (as)", "dwe8h", "edt (1,wer,345,rtz,tr t)", "nope"};

如果我只是调用s.split(","),那么在修剪后我会得到不同的结果,因为在其中一些字符串中,例如"3rncd (23uh, sdfuh)"仍然有逗号。但我不想计算括号内的逗号。有没有一种优雅的方法来解决这个问题?

可能是[在括号环境中除外逗号拆分字符串]的重复问题(https://dev59.com/qF8d5IYBdhLWcg3wcx5V) - Atri
除此之外,它是Python。 - principal-ideal-domain
你不想忽略引号内的逗号吗?我不太了解Python,但CSV解析库可以有效地处理这个问题。 - Pavel Niedoba
3个回答

5
假设 () 没有嵌套和转义。你可以使用以下方法拆分文本:
String[] arr = input.split(",(?![^()]*\\))\\s*");
,(?![^()]*\)) 这个正则表达式可以匹配非括号文本和)之后的逗号,因此忽略了括号内部的逗号。请查看RegEx Demo

在您的演示中,您选择了“pcre (php)”。这是Java使用的吗? - principal-ideal-domain
这只是演示目的。在 ",(?![^()]*\\))\\s*" 中没有任何 PCRE 特定的内容,它也适用于 Java。 - anubhava
这是一个糟糕的答案,向前查找是开放式的,依靠括号防止查找到字符串的末尾。而且它必须在找到每个逗号时执行此操作。@principal-ideal-domain 您应该注意这一点! - user557597

1

顺便说一句:我不会使用前瞻解决方案。

如果有很多逗号,前瞻将具有相对于逗号数量的对数延迟。

原因是像这样使用的前瞻可以是开放式的。如果有可能没有任何东西来终止前瞻,那么这不是一个好主意。特别是在大量数据的情况下。

每次正则表达式找到一个逗号,它都要执行这个操作 (?![^()]*\))

它的作用是向前查看直到找到括号为止。这意味着它也会匹配逗号。

如果您有一个字符串像这样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

0

即使对你而言,这也能起作用。

public static void main(String[] args) {
    String s="abc, 3rncd (23uh, sdfuh), 32h(q23q)89 (as), dwe8h, edt (1,wer,345,rtz,tr t), nope";
    String[] arr = s.split(",\\s(?!\\w+\\))");
    for (String str : arr) {
        System.out.println(str);
    }
}

输出:

abc
3rncd (23uh, sdfuh)
32h(q23q)89 (as)
dwe8h
edt (1,wer,345,rtz,tr t)
nope

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接