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

Posted

技术标签:

【中文标题】Java中的正则表达式-删除不必要的空格[重复]【英文标题】:Regex in Java - Removing unnecessary spaces [duplicate] 【发布时间】:2015-05-08 03:20:34 【问题描述】:

每次我需要一些带有正则表达式的东西时,我都很难过......

现在,我需要转一些模糊的文字... 在一个非常古老的数据库中,某些系统不允许用户格式化他们的文本......所以,用户有创意,输入如下表达式:

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 中使用正则表达式。

很抱歉这个愚蠢的问题,但我花了很多时间试图解决这个问题。

【问题讨论】:

单词之间是双空格吗? 你想把中间的双空格换成一个吗? 每个字符后跟一个空格……甚至是空格。但是你必须考虑到这是手工制作的......所以,有时,你可能会找到两个、四个甚至更多,而不是单词之间的三个空格。 【参考方案1】:

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

例子:

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", "$1");
System.out.println(s);

输出:SOME TEXT I WOULD LIKE TO HIGHLIGHT


解释:

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

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

如果您仔细观察,您会发现您想从每对中删除第二个字符(即空格),并保留第一个字符:

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 regex where 实现它

. 代表任意字符(包括空格) \s 代表任何空格

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


Ver.2(如果要删除的空格不仅位于奇数索引位置)

解决这个问题的其他方法是只删除这些空格

紧跟在非空格字符(?<=\\S)\\s之后

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

放在其他空格之前\\s(?=\\s)

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

这样你可以看到剩下一个空格(单词前面的那个),所以你的解决方案看起来像

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

【讨论】:

该表达式仅适用于 2 或 3 个空格。 @StefanA 这是 OP 在他的问题中给我们的。我怀疑 OP 示例中的字符串是通过在原始字符串中的每个字符后添加空格来精确创建的,除了最后一个。 实际上,这是“撤消”用户可能所做的事情的一种非常聪明的方法。但是@StepfanA 是对的……这可能不是我们在这些文本中可以找到的唯一情况。无论如何,谢谢你,Pshemo。【参考方案2】:

只有一个 Pattern,没有 Lookaheads,没有单词边框锚

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

说明:

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

【讨论】:

事实上,这正是我想要的。谢谢你斯特凡。现在,我必须弄清楚何时需要应用替换,因为有时,文本是使用该技术编写的,有时不是(我是否提到用户一直很有创意 :-))...我的意思是,有时您有时会发现 [A...TEXT] [A.TEXT],如果我总是替换,在第二种情况下,我将拥有 [ATEXT]。 (点而不是空格,因此可以在此评论中看到)。【参考方案3】:

如果单词被多个空格隔开,可以使用负向向前看

\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

【讨论】:

如果用户还尝试将内容与多个空格对齐,这可能会在结果句子中留下不均匀的间距。 @RaviThapliyal 是的,但在这种情况下,我们将不得不使用另一个 replaceAll 来对齐所有内容。我跳过了,因为 OP 没有明确提到与此相关的任何内容。 @nu11p01n73R 这会在中间给你两个空格。 它有效......但还有其他更优化的答案。还是谢谢你。【参考方案4】:

这个正则表达式会在中间给你一个空格,即单词之间的一个空格。

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", "$1"));

输出:

SOME TEXT I WOULD LIKE TO HIGHLIGHT

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

Regex Demo

【讨论】:

它确实有效,但我无法理解......正如我所读的那样,表达式说:[2 or more white-spaces OR 1 white-space] replaces for [white-space ],因为第 1 组总是一个空格......我理解错了吗? @AlexGouvêaVasconcelos 想法是让正则表达式先测试是否有多个空格,如果是,则将其替换为第一个。如果组中只有一个空格匹配 1 将为空,因此您将用任何内容替换这个空格(您将删除它)。 我明白了...我没有意识到跟随组的量化为其价值创造了条件,因此代表组的“$1”可能是空的... 类似于(foo)+(foo+)。对于像ZfoofooZ 这样的数据,两个正则表达式都将匹配foofoo 部分,但在第一种情况下,由于组不包括重复(+),它的值每次都会被新的foo 替换它会找到。所以我撒了一点谎,说“如果这是真的,用第一个替换它”,因为它将替换为最后一个(但由于两个值相同,它不会改变任何东西)。【参考方案5】:

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

首先,将字符之间的所有空格去掉

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

然后,将单词之间的所有多个空格替换为一个

input.replaceAll("\\s2,", " ");

所以,完整的代码如下所示

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("\\s2,", " ");

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

【讨论】:

它有效......但还有其他更优化的答案。还是谢谢你。

以上是关于Java中的正则表达式-删除不必要的空格[重复]的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式检测代码中的注释[重复]

从 JSON 字符串中删除所有不必要的空格(在 PHP 中)

带有空格的英国邮政编码的Java正则表达式[重复]

删除重复的单词、逗号和空格

Java中啥函数可以读取字符串中的空格

正则表达式选择所有不在引号中的空格?