Java 如何拆分字符串,只保留某些分隔符?

Java 如何拆分字符串,只保留某些分隔符?,java,regex,split,regex-lookarounds,Java,Regex,Split,Regex Lookarounds,我有一个类似的问题。如何使用正则表达式拆分字符串,保留某些类型的分隔符,但不保留其他类型的分隔符?具体来说,我希望保留非空白分隔符,但不保留空白分隔符 要使其具体化: "a;b c" | ["a", ";", "b", "c"] "a; ; bb c ;d" | ["a", ";", ";", "bb", "c", ";", "d"] 这可以用正则表达式干净地完成吗?如果可以,如何完成 现在我正在通过拆分要保留的角色来解决这个问题,然后再拆分另一个角色。如果正则表达式不能这样做,

我有一个类似的问题。如何使用正则表达式拆分字符串,保留某些类型的分隔符,但不保留其他类型的分隔符?具体来说,我希望保留非空白分隔符,但不保留空白分隔符

要使其具体化:

"a;b c"        | ["a", ";", "b", "c"]
"a; ; bb c ;d" | ["a", ";", ";", "bb", "c", ";", "d"]
这可以用正则表达式干净地完成吗?如果可以,如何完成

现在我正在通过拆分要保留的角色来解决这个问题,然后再拆分另一个角色。如果正则表达式不能这样做,或者不能干净地这样做,我可以坚持这种方法:

Arrays.stream(input.split("((?<=;)|(?=;))"))
        .flatMap(s -> Arrays.stream(s.split("\\s+")))
        .filter(s -> !s.isEmpty())
        .toArray(String[]::new); // In practice, I would generally use .collect(Collectors.toList()) instead

Arrays.stream(input.split)((?要在空格上拆分,或在字母和非字母之间拆分:

str.split("\\s+|(?<=\\w)(?=\\W)|(?<=\\W)(?=\\w)");

str.split(“\\s+|)(?您可以这样做:

System.out.println(String.join("-", "a; ; b c ;d".split("(?!\\G) *(?=;)|(?<=;) *| +")));

System.out.println(String.join(“-”,“a;;b c;d”).split((?!\\G)*(?=;)|(?借用@casimirithippolyte
\G
你可能想要使用的拆分技巧

\\s+|(?!\\G)()
注意:未指定分隔符

更新 基于避免在第一个空间上拆分:

(?m)(?<!^|\\s)(\\s+|)(?!$)

(?m)(?我发现一个正则表达式可以工作:

(\\s+)|((?<=;)(?=\\S)|(?<=\\S)(?=;))

我建议您捕获所需内容,而不是使用此简单模式进行拆分

([^; ]+|;)

意识到Java不支持将捕获的拆分字符添加到 拆分数组元素,我想我会尝试一个没有该元素的拆分解决方案
能力

基本上只有4种涉及空格和冒号的排列。
最后,只有空格

这是正则表达式

原始:
\s+(?=;)|(?

字符串:
“\\s+(?=;)|”(?这很好,但不会
”(?!\\G)\\s*
仅此一项就可以解决问题?这当然适用于给出的示例。@Alanmore我更新了示例,以表明我希望在同一匹配结果中包含多个连续的非空白、非分号字符。这种简化对更新后的示例不起作用。但这并不能回答有关拆分的问题在正则表达式上,这可能是构建所需元素列表这一根本问题的最佳答案。它简单、简洁、易于理解,并且不言自明。其他解决方案需要对正则表达式有相当深入的理解,并仔细评估所使用的正则表达式。但是,我不确定是否应该将其标记为accepted回答,因为拆分列表的实际问题本身也有优点。这将是此解决方案在更新后的实际Java代码,以包含\s字符类包含的所有空白,而不仅仅是空格:
Matcher Matcher=Pattern.compile(([^;\t\n\u000B\f\r]+|”).Matcher(输入);List matches=new ArrayList();while(matcher.find()){matches.add(matcher.group());}返回匹配项;
。请注意,这方面的实际Java代码比使用split要长,因为API没有提供获取所有组的一行机制。这并不能完全回答所提出的问题,因为我实际上并不关心它是否是单词字符(\w与[\p{Alpha}\p{gc=Mn}\p{gc=Me}\p{gc Mc}\p{Digit}\p{gc=Pc})相同),甚至它是否是分号。上面的Arthur的解决方案()实际上与此相同,但只检查分号和空格。为什么要使用空的捕获组“()”最后?它似乎什么都没做,没有它也能正常工作。是的,捕获组只是为了详细说明。我还更新了我的答案以满足您的新要求。请检查。@M.justin这几乎可以工作,但它包括初始空格作为附加拆分(“a”->[,“a”]而不是[“a”])。如果您想允许这些额外的空格,只需要一个断言。[我不太清楚您在说什么。当我使用Java中的String.split()将您的正则表达式应用于“a”时,它在拆分列表中给出了两个元素(空字符串和“a”)。我希望并期望它只返回一个(“a”)。我会为您进行编辑,请稍等。Split不允许您内联修剪,但您可以将“a”作为一个元素匹配,然后在元素0上向左修剪。您可以这样做吗?事实上,我想我误解了Java是如何拆分字符串的;后面的空字符串被排除在外,而不是前导字符串。
[a, ;, ;, b, c, ;, d]
([^; ]+|;)
    \s+                  # Required, suck up wsp before ;
    (?= ; )              # ;

 |                     # or,

    (?<= ; )             # ;
    \s+                  # Required, suck up wsp after ;

 |                     # or,

    (?<! \s )            # No wsp before ;
    (?= ; )              # ;

 |                     # or,

    (?<= ; )             # ;
    (?! \s )             # No wsp after ;

 |                     # or,

    \s+                  # Required wsp
    \s+                  # Required, suck up wsp before ;
    (?= ; )              # ;

 |                     # or,

    (?<= ; )             # ;
    \s+                  # Required, suck up wsp after ;

 |                     # or,

    (?<! \s )            # No wsp before ;
    (?= ; )              # ;

 |                     # or,

    (?<= ; )             # ;
    (?! \s )             # No wsp after ;

 |                     # or,

    (?<! ^ )             # No split of wsp at BOS   
    (?<! \s )
    \s+                  # Required wsp