正则表达式 (?U)\p{Punct} 缺少 Java 中的一些 Unicode 标点符号

wil*_*iam 6 java regex unicode

首先,我想删除字符串中的所有标点符号。我写了下面的代码。

\n
Pattern pattern = Pattern.compile("\\\\p{Punct}");\nMatcher matcher = pattern.matcher("!\\"#$%&\'()*+,-./:;<=>?@[\\\\]^_`{|}~\xef\xbc\x88hello\xef\xbc\x89");\nif (matcher.find())\n    System.out.println(matcher.replaceAll(""));\n
Run Code Online (Sandbox Code Playgroud)\n

替换后我得到了这个输出:\xef\xbc\x88hello\xef\xbc\x89

\n

!"#$%&\'()*+,-./:;<=>?@[\\]^_因此该模式与{|}~`之一匹配,它与官方文档匹配。

\n

但我也想删除“\xef\xbc\x88”Fullwidth Left Parenthesis U+FF08*和“\xef\xbc\x89” Fullwidth Right Parenthesis U+FF09,所以我将代码更改为:

\n
Pattern pattern = Pattern.compile("(?U)\\\\p{Punct}");\n        Matcher matcher = pattern.matcher("!\\"#$%&\'()*+,-./:;<=>?@[\\\\]^_`{|}~\xef\xbc\x88\xef\xbc\x89");\n        if (matcher.find())\n            System.out.println(matcher.replaceAll(""));\n
Run Code Online (Sandbox Code Playgroud)\n

替换后,我得到以下输出:$+<=>^|~`

\n

它确实匹配了 "\xef\xbc\x88"Fullwidth Left Parenthesis U+FF08*和 "\xef\xbc\x89" Fullwidth Right Parenthesis U+FF09,但它错过了$+<=>^|~`。

\n

我感到很困惑。为什么会发生这种事?有人可以提供一些帮助吗?

\n

Swe*_*per 9

Unicode(即当您使用 时(?U))和 POSIX(当您不使用 时(?U))对于标点符号的计算方式存在分歧。

\n

当您不使用 时(?U)\\p{Punct}匹配POSIX 标点字符类,这只是

\n
!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~\n
Run Code Online (Sandbox Code Playgroud)\n

当您使用(?U),\\p{Punct}匹配Unicode 标点符号类别时,该类别不包括上面列表中的某些字符,即:

\n
$+<=>^`|~\n
Run Code Online (Sandbox Code Playgroud)\n

例如,Unicode 类别$是“符号、货币”或 Sc。看这里

\n

如果你想匹配 $+<=>^`|~ 以及所有 Unicode 标点符号,你可以将它们都放在一个字符类中。您也可以直接使用 Unicode 类别“P”,而不用打开 Unicode 模式(?U)

\n
Pattern pattern = Pattern.compile("[\\\\p{P}$+<=>^`|~]");\nMatcher matcher = pattern.matcher("!\\"#$%&\'()*+,-./:;<=>?@[\\\\]^_`{|}~\xef\xbc\x88\xef\xbc\x89");\n// you don\'t need "find" first\nSystem.out.println(matcher.replaceAll(""));\n
Run Code Online (Sandbox Code Playgroud)\n