1. 概述
在文本处理和分析中,移除字符串中的标点符号是一个常见的操作。
在这个简短的教程中,我们将探讨如何轻松地从给定字符串中删除标点符号。
2. 问题介绍
假设我们有一个字符串:
static final String INPUT = "It's 1 W o r d (!@#$%^&*{}[];':\")<>,.";
我们可以看到,字符串 INPUT
包含数字、字母、空格以及各种标点符号。
我们的目标是从字符串中只移除标点符号,保留字母、数字和空格在结果中:
static final String EXPECTED = "Its 1 W o r d ";
在这个教程中,我们将主要使用Java标准库提供的String.replaceAll()
方法来解决这个问题。为了简化,我们将使用单元测试断言来验证结果是否符合预期。
接下来,让我们看看如何移除这些标点符号。
3. 使用正则表达式模式“*[^\sa-zA-Z0-9]”和“\p{Punct}*
我们提到使用String.replaceAll()
方法从输入字符串中移除标点符号。replaceAll()
方法基于正则表达式进行字符串替换。它会检查输入字符串,并将所有匹配我们正则表达式模式的部分替换为替换字符串。
因此,正则表达式模式是解决这个问题的关键。
由于我们希望保留字母、数字和空格在结果中,我们可以将任何非数字、非字母或非空格字符替换为空字符串。我们可以使用正则表达式的字符范围[^\\sa-zA-Z0-9]
来匹配这些字符。
接下来,让我们创建一个测试来检查是否有效:
String result = INPUT.replaceAll("[^\\sa-zA-Z0-9]", "");
assertEquals(EXPECTED, result);
如果执行测试,它将通过。正则表达式模式相当直观。对于不熟悉语法的人来说,注意以下几点可能会有帮助:
-
[^…]
- 不是\[…\]
中的任何一个字符。例如,[^0-9]
匹配任何非数字。 -
\s
- 匹配任何空白字符,如空格和制表符。
此外,Java的正则表达式引擎支持POSIX字符类别。因此,我们可以直接使用\\\\p{Punct}
字符类别来匹配任何属于!"#$%&'()*+,-./:;<=>?@\[\\\]^\_\
{|}~:`中的字符:
String result = INPUT.replaceAll("\\p{Punct}", "");
assertEquals(EXPECTED, result);
当我们运行上述测试时,它也会通过。
4. 当输入为Unicode字符串时
我们已经成功地看到了两种移除输入字符串中标点的方法。如果我们仔细观察INPUT
字符串,我们会发现它由ASCII字符组成。
可能会有人问:如果我们收到这样的字符串:
static final String UNICODE_INPUT = "3 March März 三月 březen маршировать (!@#$%^&*{}[];':\")<>,.";
除了数字3
、空格字符和标点符号,这个输入还包括英语、德语、中文、捷克语和俄语中的单词“March”。因此,与之前的INPUT
变量不同,UNICODE_INPUT
变量包含Unicode字符。
移除标点后,预期的结果应该如下所示:
static final String UNICODE_EXPECTED = "3 March März 三月 březen маршировать ";
接下来,让我们测试这两种方法是否仍然适用于这种输入:
String result1 = UNICODE_INPUT.replaceAll("[^\\sa-zA-Z0-9]", "");
assertNotEquals(UNICODE_EXPECTED, result1);
上述测试通过了。但值得注意的是,断言是assertNotEquals()
。所以,“移除[^\\sa-zA-Z0-9]
”方法并未产生预期的结果。让我们看看它实际产生的结果:
String actualResult1 = "3 March Mrz bezen ";
assertEquals(actualResult1, result1);
所以,所有非ASCII字符连同标点一起被移除了。显然,“移除[^\\sa-zA-Z0-9]
”方法对Unicode字符串不起作用。
但是,我们可以通过将“a-zA-Z”范围替换为“\p{L}”来修复它:
String result3 = UNICODE_INPUT.replaceAll("[^\\s\\p{L}0-9]", "");
assertEquals(UNICODE_EXPECTED, result3);
值得一提的是,\\p{L}
匹配任何字母,包括Unicode字符。
另一方面,“移除\\p{Punct}
”方法仍然适用于Unicode输入:
String result2 = UNICODE_INPUT.replaceAll("\\p{Punct}", "");
assertEquals(UNICODE_EXPECTED, result2);
这是因为\\\\p{Punct}
只匹配标点字符。
5. 总结
在这篇文章中,我们学习了如何使用标准的String.replaceAll()
方法从字符串中移除标点符号:
-
String.replaceAll("[^\\\\sa-zA-Z0-9]", "")
- 只适用于包含ASCII字符的输入字符串 -
String.replaceAll("\\\\p{Punct}", "")
- 适用于ASCII和Unicode字符串 -
String.replaceAll("[^\\\\s\\\\p{L}0-9]", "")
- 适用于ASCII和Unicode字符串
如往常一样,这里展示的所有代码片段都可以在GitHub上找到。