我试图找到为什么在JAVA中([\ud800-\udbff\udc00-\udfff]) 使用的此正则表达式replaceAll(regexp,"")还要删除连字符和减号字符以及代用字符。
([\ud800-\udbff\udc00-\udfff])
replaceAll(regexp,"")
这个的Unicode是\u002d这样的,因此它似乎不在任何这些范围内。
\u002d
我可以轻松删除此行为,添加&&[^\u002d]导致([\ud800-\udbff\udc00-\udfff&&[^\u002d]])
&&[^\u002d]
([\ud800-\udbff\udc00-\udfff&&[^\u002d]])
但是,由于我不知道为什么\u002d要删除它,我认为可能会删除更多未被注意的字符。
例:
String text = "A\u002dB"; System.out.println(text); String regex = "([\ud800-\udbff\udc00-\udfff])"; System.out.println(text.replaceAll(regex, "X"));
印刷品:
A-B AXB
在Java regex中,星体平面中的匹配字符(代码点U + 10000至U + 10FFFF)是一个文档不足的功能。
该答案主要涉及针对Java 6及更高版本的Oracle实现(参考实现,OpenJDK中也使用了参考实现)。
如果您碰巧使用GNU Classpath或Android,请自己测试代码,因为它们使用自己的实现。
假设您正在Oracle实施中运行正则表达式,则您的正则表达式
"([\ud800-\udbff\udc00-\udfff])"
编译如下:
StartS. Start unanchored match (minLength=1) java.util.regex.Pattern$GroupHead Pattern.union. A ∪ B: Pattern.union. A ∪ B: Pattern.rangeFor. U+D800 <= codePoint <= U+10FC00. BitClass. Match any of these 1 character(s): [U+002D] SingleS. Match code point: U+DFFF LOW SURROGATES DFFF java.util.regex.Pattern$GroupTail java.util.regex.Pattern$LastNode Node. Accept match
字符类被解析为\ud800-\udbff\udc00,-,\udfff。由于\udbff\udc00形成有效的代理对,因此它表示代码点U + 10FC00。
\ud800-\udbff\udc00
-
\udfff
\udbff\udc00
写作毫无意义:
"[\ud800-\udbff][\udc00-\udfff]"
由于Oracle的实现按代码点进行匹配,并且有效的代理对将在匹配之前转换为代码点,因此上述正则表达式无法匹配任何内容,因为它正在搜索两个连续的单独代理,它们可以构成一个有效对。
如果要匹配并删除星体平面中U + FFFF上方的所有代码点(由有效的代理对组成),加上孤立的代理(不能构成有效的代理对),则应编写以下代码:
input.replaceAll("[\ud800\udc00-\udbff\udfff\ud800-\udfff]", "");
该解决方案已经过测试,可以在Java 6和7(Oracle实现)中工作。
上面的正则表达式编译为:
StartS. Start unanchored match (minLength=1) Pattern.union. A ∪ B: Pattern.rangeFor. U+10000 <= codePoint <= U+10FFFF. Pattern.rangeFor. U+D800 <= codePoint <= U+DFFF. java.util.regex.Pattern$LastNode Node. Accept match
请注意,我用字符串文字Unicode转义序列指定字符,而不是用正则表达式语法指定转义序列。
// Only works in Java 7 input.replaceAll("[\\ud800\\udc00-\\udbff\\udfff\\ud800-\\udfff]", "")
当使用regex语法指定Java 6时,Java 6不识别代理对,因此regex识别\\ud800为一个字符并尝试编译\\udc00-\\udbff失败的范围。我们很幸运,它为此输入引发了Exception;否则,错误将不会被发现。Java 7会正确解析此正则表达式,并编译为与上述相同的结构。
\\ud800
\\udc00-\\udbff
从Java 7及更高版本开始,\x{h..h}添加了语法以支持指定BMP(基本多语言平面)之外的字符,并且建议在星体平面中指定字符的方法。
\x{h..h}
input.replaceAll("[\\x{10000}-\\x{10ffff}\ud800-\udfff]", "");
此正则表达式也可以编译为与上述相同的结构。