Java中按第一个找到的字符串拆分

26

有没有办法告诉String.split("(")函数仅按第一次出现的字符串"("进行分割?

例如:

String test = "A*B(A+B)+A*(A+B)";
test.split("(") should result to ["A*B" ,"A+B)+A*(A+B)"]
test.split(")") should result to ["A*B(A+B" ,"+A*(A+B)"]
3个回答

47

没错,绝对可以:

test.split("\\(", 2);

String.split(String,int)文档所述:

limit参数控制模式匹配的次数,因此影响结果数组的长度。如果限制n大于零,则模式最多被应用n - 1次,数组的长度将不大于n,并且数组的最后一个条目将包含所有超出最后一个匹配分隔符的输入。


ruakh,我尝试了你的答案,当我的正则表达式是"\("时,它可以正常工作,但是当我的正则表达式是"("时,它会抛出异常。你能说一下原因吗? - Chandra Sekhar
3
这是因为在Java正则表达式中,括号(有特殊的含义。例如,(34)+表示“一个或多个出现的34”,而34+表示“一个3,后跟一个或多个出现的4”。因此,反斜杠用于“引用”或“转义”括号,表示“实际的(字符”而不是使用括号的特殊含义。 - ruakh
"("在任何正则表达式解释器中都有特殊含义(也许不包括一些非常老或受限制的解释器[?] - 不确定 - 但是我可能会使用的任何解释器都有)。" - Code Jockey
还值得一提的是,第二个标记始终存在于结果数组中:assert "param=".split("=").length == 1;但是assert "param=".split("=", 2).length == 2;,第二个标记为空字符串assert "param=".split("=", 2)[1].equals(""); - Sergey Ponomarev
@stokito:不是“第二个标记始终存在于结果数组中”的真实情况;请注意,例如assert "param".split("=", 2).length == 1;。只是split没有数字参数或数字参数为0时,会丢弃尾随的空字符串。 - ruakh
显示剩余2条评论

4
test.split("\\(",2);

请查看javadoc以获取更多信息。 编辑:根据@Pedro的评论,转义括号。

会引发异常。java.util.regex.PatternSyntaxException: 未关闭的分组,索引位置在1附近。 - Pedro Ferreira

2

尝试使用这个解决方案,它比使用正则表达式更加通用、快速和简单:

public static String[] splitOnFirst(String str, char c) {
    int idx = str.indexOf(c);
    String head = str.substring(0, idx);
    String tail = str.substring(idx + 1);
    return new String[] { head, tail} ;
}

像这样测试:

String test = "A*B(A+B)+A*(A+B)";
System.out.println(Arrays.toString(splitOnFirst(test, '(')));
System.out.println(Arrays.toString(splitOnFirst(test, ')')));

2
“更简单”?我想每个人都有自己的看法。我认为正则表达式是最简单且速度足够快的方法。此外,它支持字符串,并且如果 str.indexOf(c) == -1,它不会崩溃。 - ruakh
1
它更简单,因为您不必了解正则表达式即可使用它。当然,它需要一些错误检查,但这超出了问题的范围。如果需要字符串,只需将参数“char c”更改为“String c”即可。而且,它更快,您的解决方案需要在每次调用时编译和匹配正则表达式,而OP需要转义他不知道的特殊字符。 - Óscar López
回复:“是的,它更快”:显然。我没有说正则表达式更快,只是说它足够快,而且更简单。回复:“只需将参数char c更改为String c即可解决问题”:您还需要将1更改为c.length() - ruakh
1
每个人都有自己的喜好,使用正则表达式在许多情况下也允许动态维护或调整算法,因为整个“算法”通常可以包含在一个字符串中(该字符串可以是数据库中的字段或属性文件中的单个值)。对我来说,“在开括号上分割最大数组大小为2”更简单地表示为test.split("\\(", 2);(看到了吗?我刚刚做到了),而不是你示例中的函数。此外,如果经常使用它,则编译正则表达式还可以进一步提高其效率(并不是说该表达式非常复杂)。 - Code Jockey

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