栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么代理Java正则表达式找到连字符减号-

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么代理Java正则表达式找到连字符减号-

概述和假设

在Java regex中,星体平面中的匹配字符(代码点U + 10000至U + 10FFFF)是一个文档不足的功能。

该答案主要涉及针对Java 6及更高版本的Oracle实现(参考实现,OpenJDK中也使用了参考实现)。

如果您碰巧使用GNU Classpath或Android,请自己测试代码,因为它们使用自己的实现。

幕后花絮

假设您正在Oracle实施中运行正则表达式,则您的正则表达式

"([ud800-udbffudc00-udfff])"

编译如下:

StartS. Start unanchored match (minLength=1)java.util.regex.Pattern$GroupHeadPattern.union. A ∪ B:  Pattern.union. A ∪ B:    Pattern.rangeFor. U+D800 <= prePoint <= U+10FC00.    BitClass. Match any of these 1 character(s):      [U+002D]  SingleS. Match pre point: U+DFFF LOW SURROGATES DFFFjava.util.regex.Pattern$GroupTailjava.util.regex.Pattern$LastNodeNode. Accept match

字符类被解析为

ud800-udbffudc00
-
udfff
。由于
udbffudc00
形成有效的代理对,因此它表示代码点U +
10FC00。

解决方案错误

写作毫无意义:

"[ud800-udbff][udc00-udfff]"

由于Oracle的实现按代码点进行匹配,并且有效的代理对将在匹配之前转换为代码点,因此上述正则表达式无法匹配任何内容,因为它正在搜索两个连续的单独代理,它们可以构成一个有效对。

如果要匹配并删除星体平面中U + FFFF上方的所有代码点(由有效的代理对组成),加上孤立的代理(不能构成有效的代理对),则应编写以下代码:

input.replaceAll("[ud800udc00-udbffudfffud800-udfff]", "");

该解决方案已经过测试,可以在Java 6和7(Oracle实现)中工作。

上面的正则表达式编译为:

StartS. Start unanchored match (minLength=1)Pattern.union. A ∪ B:  Pattern.rangeFor. U+10000 <= prePoint <= U+10FFFF.  Pattern.rangeFor. U+D800 <= prePoint <= U+DFFF.java.util.regex.Pattern$LastNodeNode. Accept match

请注意,我用字符串文字Unipre转义序列指定字符,而不是用正则表达式语法指定转义序列。

// only works in Java 7input.replaceAll("[\ud800\udc00-\udbff\udfff\ud800-\udfff]", "")

当使用regex语法指定Java 6时,Java
6不识别代理对,因此regex识别

\ud800
为一个字符并尝试编译
\udc00-\udbff
失败的范围。我们很幸运,它为此输入引发了Exception;否则,错误将不会被发现。Java
7会正确解析此正则表达式,并编译为与上述相同的结构。


从Java 7及更高版本开始,

x{h..h}
添加了语法以支持指定BMP(基本多语言平面)之外的字符,并且建议在星体平面中指定字符的方法。

input.replaceAll("[\x{10000}-\x{10ffff}ud800-udfff]", "");

此正则表达式也可以编译为与上述相同的结构。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/392507.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号