我有以下代码段:
private static final Pattern ESCAPER_PATTERN = Pattern.compile("[^a-zA-Z0-9\\p{P}\\s]*");
/**
* @param args
*/
public static void main(String[] args)
{
String unaccentedText = "Aa123 \\/*-+.=+:/;.,?u%µ£$*^¨-)ac!e§('\"e&€#²³~´][{^";
System.out.println(ESCAPER_PATTERN.matcher(unaccentedText).replaceAll(""));
}
当我使用JDK 7执行此操作时,我得到的输出是:
Aa123 \/*-.:/;.,?u%*-)ac!e('"e&#][{
当我用JDK 8执行相同操作时,我得到的输出是:
Aa123 \/*-.:/;.,?u%*-)ac!e§('"e&#][{
请注意,未使用JDK 8删除部分符号§。
请告诉我在JDK 8的情况下使用的正则表达式以匹配部分符号 - 以及jdks之间行为差异的原因。
答案 0 :(得分:13)
U+00A7 SECTION SIGN
中的字符§
已从类别So(符号,其他)更改为类别Po(标点,其他):
UnicodeData.txt
- U + 00A7,U + 00B6,U + 0F14,U + 1360和U + 10102从gc = So变为gc = Po。
由于Java在版本7中使用Unicode 6.1.0,在版本8中使用了Unicode 6.0.0,因此它解释了结果的不同之处。由于\p{P}
现在属于标点符号类别,因此它在Java 8中与!
匹配。
由于常规标点符号(如#
,"
,"[^a-zA-Z0-9\\p{P}\\s&&[^\u00a7]]"
,...也属于Po类别,因此我们无法真正删除此子类别。
下一个明显的解决方案是使用字符集交集删除不需要的字符:
[^a-zA-Z0-9\p{P}\s&&[^§]]
Start. Start unanchored match (minLength=1)
Pattern.intersection. S ∩ T:
Pattern.setDifference. S ∖ T:
Pattern.setDifference. S ∖ T:
Pattern.setDifference. S ∖ T:
Pattern.setDifference. S ∖ T:
CharProperty.complement. S̄:
Pattern.rangeFor. U+0061 <= codePoint <= U+007A.
Pattern.rangeFor. U+0041 <= codePoint <= U+005A.
Pattern.rangeFor. U+0030 <= codePoint <= U+0039.
DEBUG charProp: java.util.regex.Pattern$Category
Ctype. POSIX (US-ASCII): SPACE
CharProperty.complement. S̄:
BitClass. Match any of these 1 character(s):
§
java.util.regex.Pattern$LastNode
Node. Accept match
...但等一下,有Unicode 6.2.0,上面的正则表达式编译为:
[^a-zA-Z0-9\p{P}\s]
...解析为[^§]
与[a-zA-Z0-9\p{P}\s]
相交,而非([^§]
与"[[^a-zA-Z0-9\\p{P}\\s]\u00a7]"
相交)。
要解决上述问题,工作解决方案是:
[[^a-zA-Z0-9\p{P}\s]§]
Start. Start unanchored match (minLength=1)
Pattern.union. S ∪ T:
Pattern.setDifference. S ∖ T:
Pattern.setDifference. S ∖ T:
Pattern.setDifference. S ∖ T:
Pattern.setDifference. S ∖ T:
CharProperty.complement. S̄:
Pattern.rangeFor. U+0061 <= codePoint <= U+007A.
Pattern.rangeFor. U+0041 <= codePoint <= U+005A.
Pattern.rangeFor. U+0030 <= codePoint <= U+0039.
DEBUG charProp: java.util.regex.Pattern$Category
Ctype. POSIX (US-ASCII): SPACE
BitClass. Match any of these 1 character(s):
§
java.util.regex.Pattern$LastNode
Node. Accept match
编译为:
§
这次+
正确地包含在角色类中,因此该符号将被删除。
请注意,我已删除量词以用于演示目的。请将量词添加回代码中的字符类,最好是一个或多个 {{1}}量词,而不是问题中使用的零或更多量词。