一尘不染

如何用条件分割字符串

java

分割字符串时,如何确定 分隔符是否位于两个字符之间,将不会考虑该分隔符

// Input
String string = "a,b,[c,d],e";
String[] split = string.split(",");
// Output
split[0] // "a"
split[1] // "b"
split[2] // "[c"
split[3] // "d]"
split[4] // "e"
// Required
split[0] // "a"
split[1] // "b"
split[2] // "[c,d]"
split[3] // "e"

阅读 364

收藏
2020-12-03

共1个答案

一尘不染

答案结尾处的首选方法

看来您正在寻找环顾四周的机制。

例如,如果您想在没有foo之前和bar之后没有空格的空白处进行拆分,则您的代码可以像

split("(?<!foo)\\s(?!bar)")

更新 (假设没有任何嵌套,[...]并且它们的格式正确,例如全部[用封闭]):

您的情况似乎更复杂。你能做的就是接受,如果

  • 它没有任何东西[]之后,
  • 或者如果[该逗号后的第一个左括号,则]该逗号与其本身之间没有右括号,否则就意味着该逗号位于区域之内,例如
    [ , ] [
    

    ^ ^ ^ - first [ after tested comma
    | +---- one ] between tested comma and first [ after it
    +------ tested comma

因此您的代码可能看起来像
(这是原始版本,但下面是一些简化的版本)

split(",(?=[^\\]]*(\\[|$))")

这个正则表达式是基于这样的想法:您不想接受的逗号在内部[foo,bar]。但是,如何确定我们在此类块的内部(或外部)呢?

  1. 如果性格里面那么就不会有[之后的字符,直到我们找到](旁边[发现后会出现]的情况下,像[a,b],[c,d]之间的逗号ab没有[,直到它找到],但可以有一些新的领域[..]后,这ofcourse打头[
  2. 如果字符在[...]区域之外,则下一个字符之后只能显示非]字符,直到找到[...]区域的开始,否则我们将读取字符串的结尾。

第二种情况是您感兴趣的情况。因此,我们需要创建一个regex,它接受,]在其之后为non的regex (它不在inside
[...]),直到找到[或读取字符串的结尾(由表示$

这样的正则表达式可以写成

  • , 逗号
  • (?=...) 在它之后
  • [^\\]]*(\\[|$)
    • [^\\]]*零个或多个非]字符(]需要以元字符转义)
    • (\\[|$)后面有[(也需要在正则表达式中转义)或字符串结尾的字符串

小简化分割版

string.split(",(?![^\\[]*\\])");

意思是:分割逗号,,逗号之后没有((?!...)未用表示)未关闭](被测试的逗号与本身之间]没有unclose的形式[,可以写成[^\\[]*\\]


首选方法

为了避免这种复杂的正则表达式,请不要使用splitPattern和Matcher类,它们将搜索类似[...]或非逗号的区域。

String string = "a,b,[c,d],e";
Pattern p = Pattern.compile("\\[.*?\\]|[^,]+");
Matcher m = p.matcher(string);
while (m.find())
    System.out.println(m.group());

输出:

a
b
[c,d]
e
2020-12-03