如何用一个空行替换多个空格和换行符

6

如何在字符串中去除多余的空格和换行符,但至少保留每个空行组中的一个空行。

例如,将以下输入:

"This      is



a        string.




Something."

为了

"This is

a string.

Something."

我正在使用.trim()来清除字符串开头和结尾的空格,但我找不到可以删除字符串中多余的空格和换行符的方法。我想只保留一个空格和一个换行符。
3个回答

9

一行代码解决多个空格/换行符问题,但至少保留一个空白行:

str = str.replaceAll("(?m)(^ *| +(?= |$))", "").replaceAll("(?m)^$([\r\n]+?)(^$[\r\n]+?^)+", "$1");

每一行都被修剪了。


这是一些测试代码:

String str = "   This       is\r\n    " + 
        "\r\n" + 
        "   \r\n   " + 
        " \r    \n   \n  " +
        "\r\n" + 
        "                a        string.   ";
str = str.trim().replaceAll("(?m)(^ *| +(?= |$))", "").replaceAll("(?m)^$([\r\n]+?)(^$[\r\n]+?^)+", "$1");
System.out.println(str);

输出:

This is

a string.

1
这个正则表达式让我头烟了起来,但是因为这个一行代码还是给一个加1。 - A4L
我来提个交易:如果您接受这个答案,我会解释正则表达式的 :) - Bohemian
很遗憾,我不是 OP 的所有者,所以我不能接受它。我可以通过查找Pattern的 javadoc 来自己解释那些特殊的构造,但如果您将您的解释放在答案中供其他用户参考,那就太好了;-) ... 另外,我刚刚测试了一下,它似乎会在最后一行开头留下一个空格 -> ' a string.' - A4L
2
@A4L 我已经修复了关于前导空格的正则表达式:我改变了第一个正则表达式中交替的顺序,首先匹配行首的空格,然后如果没有找到,则匹配其他多个空格(正则表达式将按照编码顺序找到交替匹配)。解释正则表达式需要一些时间。我现在没有时间 - 也许以后会告诉你。 - Bohemian
1
谢谢!我会接受这个答案。A4L写了一个好的解决方案,但我认为你的一行代码更好。 - user3051755
显示剩余2条评论

1
之前的建议将修剪所有空格,包括换行符,并将它们替换为一个空格。
 text.replaceAll("\\n\\s*\\n", "\\n").replaceAll("[ \\t\\x0B\\f]+", " ").trim());

首先,它将两个换行符之间仅有的空格替换为单个换行符,然后忽略换行符将其他任何空格缩减为一个空格。


1
这是我在进行一些测试后得出的结果...
public String keepOneWS(String str) {
    Pattern p = Pattern.compile("(\\s+)");
    Matcher m = p.matcher(str);

    Pattern pBlank = Pattern.compile("[ \t]+");
    String newLineReplacement = System.getProperty("line.separator") + 
            System.getProperty("line.separator");

    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        if(pBlank.matcher(m.group(1)).matches()) {
            m.appendReplacement(sb, " ");   
        } else {
            m.appendReplacement(sb, newLineReplacement);
        }
    }
    m.appendTail(sb);

    return sb.toString().trim();
}

public void testKeepOneWS()  {
    String str = "   This   \t    is\r\n    " + 
            "\r\n" + 
            "   \r\n   " + 
            " \r    \n  \t  \n  " +
            "\r\n" + 
            "                a   \t     string.   \t ";
    String expected = "This is" + System.getProperty("line.separator")+ 
            System.getProperty("line.separator") + "a string.";
    String actual = keepOneWS(str);
    System.out.println("'" + actual + "'");
    assertEquals(expected, actual);
}

在捕获一组空格后,将检查它是否仅由空格组成,如果是,则将该组替换为一个单独的空格,否则该组由空格和行终止符组成,在这种情况下,该组将被替换为一个行终止符。
输出结果为:
'This is

a string.' 

谢谢您的回答,如果有两个以上的换行符,我想保留一个空行,并删除其他空行,就像我的示例一样。我知道我在问题中的解释不好,因为我写了我只想保留一个空格和一个换行符。我忘记了一个换行符是用于新行,而两个换行符是用于一个空行。我希望您明白我想说什么。 - user3051755
@user3051755,我已经编辑了答案,这对你有用吗?你可以尝试在正则表达式中调整多重性,上面的示例中我使用+表示至少一个或更多,你可以使用{2,}表示至少两个或更多。 - A4L
这正是我所需要的。非常感谢! - user3051755

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