当前位置: 首页 > 面试题库 >

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

濮俊美
2023-03-14
问题内容

我试图找到为什么在JAVA中([\ud800-\udbff\udc00-\udfff])
使用的此正则表达式replaceAll(regexp,"")还要删除连字符和减号字符以及代用字符。

这个的Unicode是\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]"

由于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会正确解析此正则表达式,并编译为与上述相同的结构。

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

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

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



 类似资料:
  • 本文向大家介绍字符类:减法-Java正则表达式,包括了字符类:减法-Java正则表达式的使用技巧和注意事项,需要的朋友参考一下 您可以从另一个范围中减去一个范围,并将其用作新范围。您可以使用字符类的两个变体来实现这一点,即取反和交集。 例如,范围[al]和[^ eh]的交集给您字符a至l作为愤怒减去字符[eh] 示例 输出结果

  • 问题内容: 我正在尝试匹配\ ^ c形式的控制字符,其中c是控制字符的任何有效字符。我有这个正则表达式,但目前无法使用: 我认为问题在于,插入符号(^)是正则表达式解析引擎的一部分。 问题答案: 使用pattern 匹配形式的ASCII文本字符串,仅此而已。将形式的ASCII文本字符串与模式匹配。你不妨约束点缀到,所以。对于方括号字符类而言,它更容易阅读,因此对于原义BACKSLASH,其后是原义

  • 问题内容: 当匹配某些字符(例如换行符)时,可以使用正则表达式“ \\ n”或仅使用“ \ n”。例如,以下将字符串拆分为行数组: 但是以下内容同样适用: 我的问题: 上面两个是 完全 一样地工作,还是有细微的差别?如果是后者,能否举个例子,说明您得到不同的结果? 还是仅在[可能/理论]表现上有所不同? 问题答案: 在当前情况下没有区别。通常的字符串转义序列是在单个反斜杠的帮助下形成的,然后有效的

  • 本文向大家介绍正则表达式“ [[X?+]””元字符Java,包括了正则表达式“ [[X?+]””元字符Java的使用技巧和注意事项,需要的朋友参考一下 可能量词[X?+]匹配一次存在的X或根本不存在的X。 示例 输出结果

  • 主要内容:实例下表包含了元字符的完整列表以及它们在正则表达式上下文中的行为: 字符 描述 \ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。 ^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或

  • 我用Python编写了这个正则表达式并在regex101上进行了测试,但它仍然没有按照我想要的方式工作: 我试图找到的是一种模式,其中字符串可以选择以这些符号之一开头或结尾,中间只有数字: 该列表包括破折号、正斜杠、反斜杠、括号、符号、空格和句号。如果字符串只包含中间的数字,并且在字符串的开头和/或结尾有可选标点,则搜索应返回true。 此正则表达式似乎适用于大多数情况,但如果我在中间的数字中添加