Java 中的正则表达式 - 删除不必要的空格

Regex in Java - Removing unnecessary spaces

每次我需要一些正则表达式的时候我都很难过...

现在,我需要转一些模糊的文字... 在一个非常旧的数据库中,某些系统不允许用户格式化他们的文本......因此,用户发挥了创造力,输入了如下表达式:

S O M E   T E X T   I   W O U L D   L I K E   T O   H I G H L I G H T

我的问题是,我怎样才能把那段文字变成:

SOME TEXT I WOULD LIKE TO HIGHLIGHT

使用 Java 中的正则表达式。

很抱歉这个愚蠢的问题,但我花了比预期更多的时间来解决这个问题。

如果单词被多个空格隔开,你可以使用negative look ahead as

\s(?!\s)

Regex demo

测试

"S O M E   T E X T   I   W O U L D   L I K E   T O   H I G H L I G H T"
.replaceAll("\s(?!\s)", "")
.replaceAll("\s+", " ");
=> SOME TEXT I WOULD LIKE TO HIGHLIGHT

只有一种模式,没有 Lookaheads,没有文字边框锚点

text.replaceAll("\s(\s?)\s*", "")

解释:

  • 替换任何最小长度为 1 (\s) 的空白序列
  • 如果下一个字符是空格((\s?) 匹配)=> 替换为空格
  • else ((\s?) 不匹配)替换为空字符串
  • 捕获 (\s*)
  • 之后的所有空格

如果所有单词之间保证有两个或更多个空格则:

  • 首先去掉字符之间的所有空格为

    input.replaceAll("(?<=\S)\s(?=\S)", "");
    
  • 然后,将单词之间的所有多个空格替换为一个

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

所以,完整的代码看起来像

String input = "S O M E   T E X T   I   W O U L D   L I K E   T O   H I G H L I G H T";
input = input.replaceAll("(?<=\S)\s(?=\S)", "").replaceAll("\s{2,}", " ");

System.out.println(input); // SOME TEXT I WOULD LIKE TO HIGHLIGHT

此正则表达式将在中间为您提供一个 space,即单词之间的一个 space。

String r = "S O M E   T E X T   I   W O U L D   L I K E   T O   H I G H L I G H T";
System.out.println(r.replaceAll("(\s){2,}|\s", ""));

输出:

SOME TEXT I WOULD LIKE TO HIGHLIGHT

这背后的想法是,上面的正则表达式将从两个或多个连续的 space 和所有其他 space 或进一步匹配中捕获单个 space。将匹配的 spaces 替换为组索引 1 内的字符将为您提供所需的输出。

Regex Demo

所以你可以使用replaceAll("(.)\s", "")

示例:

String s = "S O M E   T E X T   I   W O U L D   L I K E   T O   H I G H L I G H T";
s = s.replaceAll("(.)\s", "");
System.out.println(s);

输出:SOME TEXT I WOULD LIKE TO HIGHLIGHT


解释:

将您的文本视为两个字符块(我将用 ^^## 标记它们)。

S O M E   T E X T
^^##^^##^^##^^##

如果仔细观察,您会注意到您要从每对中删除第二个字符(即 space),并保留第一个字符:

S O M E   T E X T
^ # ^ # ^ # ^ # T - T will not be affected (will stay) 
                    because it doesn't have space after it.

您可以使用 (.)\s 正则表达式实现它,其中

  • .表示任意字符(包括space)
  • \s代表任意白色space

这样第一个字符将被放置在组中(索引为 1),这允许我们通过 $x 在替换部分中使用此部分的匹配,其中 x 表示组索引.


Ver.2(如果要删除的 space 不仅在奇数索引位置)

解决此问题的其他方法是仅删除这些 space,其中

  • 紧跟在非space字符(?<=\S)\s

    之后
    S O M E       T E X T
     ^ ^ ^ ^       ^ ^ ^
    
  • 排在其他 space 之前 \s(?=\s)

    S O M E       T E X T
     ^ ^ ^ ^#####  ^ ^ ^
    

这样你可以看到左边有一个 space(单词前面的那个)所以你的解决方案看起来像

s = s.replaceAll("(?<=\S)\s|\s+(?=\s)", "");