如何拆分字符串,同时保留分隔符?

新手上路,请多包涵

我有一个多行字符串,由一组不同的分隔符分隔:

 (Text1)(DelimiterA)(Text2)(DelimiterC)(Text3)(DelimiterB)(Text4)

我可以使用 String.split 将这个字符串分成几个部分,但似乎我无法获得与定界符正则表达式匹配的实际字符串。

换句话说,这就是我得到的:

  • Text1
  • Text2
  • Text3
  • Text4

这就是我要的

  • Text1
  • DelimiterA
  • Text2
  • DelimiterC
  • Text3
  • DelimiterB
  • Text4

是否有任何 JDK 方法可以使用定界符正则表达式拆分字符串,同时保留定界符?

原文由 Daniel Rikowski 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 552
2 个回答

您可以使用 lookahead 和 lookbehind,它们是正则表达式的特性。

 System.out.println(Arrays.toString("a;b;c;d".split("(?<=;)")));
System.out.println(Arrays.toString("a;b;c;d".split("(?=;)")));
System.out.println(Arrays.toString("a;b;c;d".split("((?<=;)|(?=;))")));

你会得到:

 [a;, b;, c;, d]
[a, ;b, ;c, ;d]
[a, ;, b, ;, c, ;, d]

最后一个是你想要的。

((?<=;)|(?=;)) 等于在 ; 之前或 ; --- 之后选择一个空字符。

编辑: Fabian Steeg 关于可读性的评论是有效的。可读性始终是正则表达式的问题。为了使正则表达式更具可读性,我所做的一件事是创建一个变量,其名称代表正则表达式的作用。您甚至可以放置占位符(例如 %1$s )并使用 Java 的 String.format 将占位符替换为您需要使用的实际字符串;例如:

 static public final String WITH_DELIMITER = "((?<=%1$s)|(?=%1$s))";

public void someMethod() {
    final String[] aEach = "a;b;c;d".split(String.format(WITH_DELIMITER, ";"));
    ...
}

原文由 NawaMan 发布,翻译遵循 CC BY-SA 4.0 许可协议

您想使用环视,并在零宽度匹配上拆分。这里有些例子:

 public class SplitNDump {
    static void dump(String[] arr) {
        for (String s : arr) {
            System.out.format("[%s]", s);
        }
        System.out.println();
    }
    public static void main(String[] args) {
        dump("1,234,567,890".split(","));
        // "[1][234][567][890]"
        dump("1,234,567,890".split("(?=,)"));
        // "[1][,234][,567][,890]"
        dump("1,234,567,890".split("(?<=,)"));
        // "[1,][234,][567,][890]"
        dump("1,234,567,890".split("(?<=,)|(?=,)"));
        // "[1][,][234][,][567][,][890]"

        dump(":a:bb::c:".split("(?=:)|(?<=:)"));
        // "[][:][a][:][bb][:][:][c][:]"
        dump(":a:bb::c:".split("(?=(?!^):)|(?<=:)"));
        // "[:][a][:][bb][:][:][c][:]"
        dump(":::a::::b  b::c:".split("(?=(?!^):)(?<!:)|(?!:)(?<=:)"));
        // "[:::][a][::::][b  b][::][c][:]"
        dump("a,bb:::c  d..e".split("(?!^)\\b"));
        // "[a][,][bb][:::][c][  ][d][..][e]"

        dump("ArrayIndexOutOfBoundsException".split("(?<=[a-z])(?=[A-Z])"));
        // "[Array][Index][Out][Of][Bounds][Exception]"
        dump("1234567890".split("(?<=\\G.{4})"));
        // "[1234][5678][90]"

        // Split at the end of each run of letter
        dump("Boooyaaaah! Yippieeee!!".split("(?<=(?=(.)\\1(?!\\1))..)"));
        // "[Booo][yaaaa][h! Yipp][ieeee][!!]"
    }
}

是的,这是最后一个模式中的三重嵌套断言。

相关问题

也可以看看

原文由 polygenelubricants 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题