Java如何将字符串中的2个或多个空格替换为单个空格并删除前导和尾随空格

339

我在Java中寻找一种快速简单的方法来更改这个字符串

" hello     there   "

变成这样的形式

"hello there"

我想把字符串中所有的多个空格替换为一个空格,但我也想让字符串开头的一个或多个空格消失。

类似这样的代码可以部分实现:

String mytext = " hello     there   ";
mytext = mytext.replaceAll("( )+", " ");

但还不完全相同。


9
您应该考虑接受一个答案。这样做可以让后来的人更轻松地选择一个明确的解决方案。 - Paul Rooney
2
这是其中一种最推荐的方法。String nameWithProperSpacing = StringUtils.normalizeSpace( stringWithLotOfSpaces ); - Kunal Vohra
4
s = s.replaceAll("\s+"," "); - Saroj Kumar Sahoo
32个回答

574

试试这个:

String after = before.trim().replaceAll(" +", " ");

参见


没有trim()的正则表达式

也可以只用一个replaceAll实现这个功能,但是这种方法比trim()方案难以阅读。不过,为了展示正则表达式的功能,这里还是提供了该方法:

    String[] tests = {
        "  x  ",          // [x]
        "  1   2   3  ",  // [1 2 3]
        "",               // []
        "   ",            // []
    };
    for (String test : tests) {
        System.out.format("[%s]%n",
            test.replaceAll("^ +| +$|( )+", "$1")
        );
    }

这里有3个备选方案:

  • ^_+ :字符串开头的任意空格序列
    • 匹配并替换为$1,它捕获空字符串
  • _+$ :字符串末尾的任意空格序列
    • 匹配并替换为$1,它捕获空字符串
  • (_)+ :任何不符合以上两种情况的中间位置的空格序列
    • 匹配并替换为$1,它捕获单个空格

另请参阅


13
+1,特别要注意的是先使用trim()再使用replaceAll()比相反顺序使用的内存消耗要小一些。虽然差别不大,但如果这个操作被频繁地调用,尤其是存在大量“可修剪空格”的情况下,这种差别可能会逐渐累积。(trim()并没有真正去除额外的空格,它只是通过移动起始和结束值来隐藏它们。底层的char[]仍然保持不变。) - corsiKa
2
这只是一个细节,但我认为 ( ) +( ){2,} 应该(非常)稍微更有效一些 ;) - sp00m
6
不错的正则表达式。注意:将空格 替换为 \\s 将会用所需字符替换任何一组空白字符。 - djmj
1
请注意,( )+ 部分将匹配一个空格并用一个空格替换它。也许 (<space><space>+) 更好,因此仅在存在多个空格且替换将对字符串进行净更改时才进行匹配。 - Lee Meador
3
正如Lee Meador所提到的那样,使用两个空格的 .trim().replaceAll(" +", " ") 要比使用一个空格的 .trim().replaceAll(" +", " ") 更快。对于只有单个空格和全部都是双倍空格的字符串进行了定时测试,并且在执行很多操作(取决于环境,可能达到数百万次甚至更多)时,两者都显著更快。 - Gary S. Weaver
显示剩余2条评论

179

你只需要:

replaceAll("\\s{2,}", " ").trim();

用正则表达式匹配一个或多个空格,并将它们替换为一个单独的空格,然后在开头和结尾删除空格(实际上你可以通过先修整再匹配的方式来翻转该过程,从而使正则表达式更快,正如某人所指出的那样)。

要快速测试这一点,请尝试:

System.out.println(new String(" hello     there   ").trim().replaceAll("\\s{2,}", " "));

并且它会返回:

"hello there"

小心,如果你认为正则表达式中的 \\s 存在意味着它会将一个或多个空格字符序列缩减为单个空格。这并不总是有效。例如,如果您的原始字符串包含换行符,并且两侧都有非空格字符,则它不会用空格替换该换行符。这是因为 {2,} 要求至少有 2 个相邻的空格字符。 - Matt Wallis

68
使用Apache commons StringUtils.normalizeSpace(String str)方法。请参阅此处的文档

25

trim()方法会移除字符串前后的空格,使用replaceAll("regex", "string to replace")方法中的正则表达式 "\s+" 可以匹配多个空格并将其替换为一个空格。

myText = myText.trim().replaceAll("\\s+"," ");

24

这段代码完美地运行在我的电脑上:sValue = sValue.trim().replaceAll("\\s+", " ");


19
以下代码将压缩单词间的任何空白,并删除字符串开头和结尾处的任何空白。
String input = "\n\n\n  a     string with     many    spaces,    \n"+
               " a \t tab and a newline\n\n";
String output = input.trim().replaceAll("\\s+", " ");
System.out.println(output);

这将输出一个带有多个空格、制表符和换行符的字符串。

请注意,任何非可打印字符,包括空格、制表符和换行符,都将被压缩或删除。


更多信息请参见相应文档:


17
"[ ]{2,}"

这将匹配多个空格。

String mytext = " hello     there   ";
//without trim -> " hello there"
//with trim -> "hello there"
mytext = mytext.trim().replaceAll("[ ]{2,}", " ");
System.out.println(mytext);

输出:

hello there

15
为消除字符串开头和结尾处的空格,请使用String#trim()方法,然后使用mytext.replaceAll("( )+", " ")

12

您可以先使用String.trim(),然后对结果应用正则表达式替换命令。


10

试试这个。

示例代码

String str = " hello     there   ";
System.out.println(str.replaceAll("( +)"," ").trim());

输出

hello there

首先会将所有的空格替换为单个空格。接着我们需要做的是去除字符串的首尾空格,因为如果字符串的开头或结尾有空格,它会将其替换为单个空格。所以我们需要对其进行修剪(trim)。这样您就可以得到想要的字符串了。


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