【问题标题】:Java split string with '\r\n', '\r' or '\n' and keep it with preceding substringJava 用 '\r\n'、'\r' 或 '\n' 分割字符串,并与前面的子字符串保持一致
【发布时间】:2019-08-29 04:11:25
【问题描述】:

我的输入字符串包含混合类型的行分隔符,包括“\r\n”、“\r”或“\n”。我想拆分字符串并将行分隔符与它前面的子字符串保持一致。我关注了下面的两个帖子

How to split a string, but also keep the delimiters?

Split Java String by New Line

然后想出类似的东西:

String input = "1 dog \r\n 2 cat";
String[] output = input.split( "(?<=((\\r\\n)|\\r|\\n))")));

输出为["1 dog\r", "\n", " 2 cat"],但所需的输出为["1 dog\r\n", " 2 cat"]

如果我将输入更改为String input = "1 dog \r 2 cat";String input = "1 dog \n 2 cat";,我的代码可以产生所需的输出。请指教。提前致谢。

【问题讨论】:

    标签: java regex


    【解决方案1】:

    你得到你的结果["1 dog\r", "\n", " 2 cat"],因为你的模式使用了一个交替匹配(\r\n)\r\n

    当示例字符串中遇到\r\n 时,在\r 之后的lookbehind 断言为真,并且将第一次拆分。

    那么在\n 之后,lookbehind 断言将是真的,并且会第二次分裂。

    您可能会做的是在积极的后视中使用\R 来断言左侧是unicode newline sequence

    String input = "1 dog \r\n 2 cat";
    String[] output = input.split("(?<=\\R)");
    

    Java demo

    修复正则表达式的另一种方法是将其设为atomic group

    (?<=(?>\\r\\n|\\r|\\n))
    

    Java demo

    读取this post,当\r使用原子组在后向匹配时,以下\n也匹配。

    【讨论】:

    • 非常好的答案!使用\R 比我的解决方案更好! +1
    • 如果你解释一下 OP 正则表达式无法工作的原因,我认为这个答案会更好看。
    • @Allan 谢谢你,我已经在 J​​ava 演示中重用了你的一部分 printASCII 来列出字符,如果你同意的话。
    • @WiktorStribiżew 这是一个公平的观点,我已经添加了关于 OP 正则表达式的解释。
    • 是的,但为什么\R 工作可能更有趣,而为什么\R 工作的答案也将向 OP 展示如何修复他们的正则表达式。
    【解决方案2】:

    如果您使用以下正则表达式:(?&lt;=\\r\\n|\\r(?!\\n)|\\n) 来拆分您的字符串,它将按预期工作。

    您的正则表达式发生的情况是,当遇到\r\n 时,后向断言将为真(?&lt;=\r),它会在\r 之后拆分字符串。

    这就是为什么我在\r 之后添加了一个否定的前瞻(?!\n) 以强制\r 之后的字符不是\n。这将防止\r\n 之间的拆分并保持其为一个整体。

    演示:https://regex101.com/r/H6PNmY/1/(为了便于阅读,我将 \r 替换为 a\n 替换为 b

    当你把它放回你的代码中时:

    String input = "1 dog \r\n 2 cat, 1 car \r 2 planes, 1 apple \n 2 peaches";
    String[] output = input.split("(?<=\\r\\n|\\r(?!\\n)|\\n)");
    
    for(int i=0; i<output.length; i++)
    {
      printASCII(output[i]);
      System.out.println("===");        
    }
    

    printASCII 定义为:

    public static void printASCII(String in)
    {
        for(int i=0; i<in.length(); i++)
            System.out.println("The ASCII value of " + in.charAt(i) + "  =  " + (int)in.charAt(i) );
    }
    

    它为您提供以下输出:

    The ASCII value of 1  =  49
    The ASCII value of    =  32
    The ASCII value of d  =  100
    The ASCII value of o  =  111
    The ASCII value of g  =  103
    The ASCII value of    =  32
    The ASCII value of 
      =  13
    The ASCII value of 
      =  10
    ===
    The ASCII value of    =  32
    The ASCII value of 2  =  50
    The ASCII value of    =  32
    The ASCII value of c  =  99
    The ASCII value of a  =  97
    The ASCII value of t  =  116
    The ASCII value of ,  =  44
    The ASCII value of    =  32
    The ASCII value of 1  =  49
    The ASCII value of    =  32
    The ASCII value of c  =  99
    The ASCII value of a  =  97
    The ASCII value of r  =  114
    The ASCII value of    =  32
    The ASCII value of 
      =  13
    ===
    The ASCII value of    =  32
    The ASCII value of 2  =  50
    The ASCII value of    =  32
    The ASCII value of p  =  112
    The ASCII value of l  =  108
    The ASCII value of a  =  97
    The ASCII value of n  =  110
    The ASCII value of e  =  101
    The ASCII value of s  =  115
    The ASCII value of ,  =  44
    The ASCII value of    =  32
    The ASCII value of 1  =  49
    The ASCII value of    =  32
    The ASCII value of a  =  97
    The ASCII value of p  =  112
    The ASCII value of p  =  112
    The ASCII value of l  =  108
    The ASCII value of e  =  101
    The ASCII value of    =  32
    The ASCII value of 
      =  10
    ===
    The ASCII value of    =  32
    The ASCII value of 2  =  50
    The ASCII value of    =  32
    The ASCII value of p  =  112
    The ASCII value of e  =  101
    The ASCII value of a  =  97
    The ASCII value of c  =  99
    The ASCII value of h  =  104
    The ASCII value of e  =  101
    The ASCII value of s  =  115
    ===
    

    这表明 EOL 字符已按照您的要求妥善保存。

    ASCII 表: https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.networkcomm/conversion_table.htm

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-12
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      相关资源
      最近更新 更多