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

2024-01-30

我试图找出为什么 JAVA 中存在这个正则表达式([\ud800-\udbff\udc00-\udfff])用于replaceAll(regexp,"")还将删除连字符减号以及代理字符。

这个的 Unicode 是\u002d所以它似乎不在任何这些范围之内。

我可以轻松地删除这种行为添加&&[^\u002d]导致([\ud800-\udbff\udc00-\udfff&&[^\u002d]])

但是,由于我不知道为什么会这样\u002d被删除,我认为可能会有更多未被注意到的字符被删除。

Example:

String text = "A\u002dB";
System.out.println(text);
String regex = "([\ud800-\udbff\udc00-\udfff])";
System.out.println(text.replaceAll(regex, "X"));

prints:

A-B
AXB

概述和假设

匹配星体层中的字符(代码点 U+10000 到 U+10FFFF)一直是 Java 正则表达式中记录不足的功能。

这个答案主要涉及Oracle对Java版本6及以上版本的实现(参考实现,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. Since \udbff\udc00形成有效的代理对,它代表代码点 U+10FC00。

错误的解决方案

写起来没有意义:

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

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

Solution

如果您想匹配并删除星体层中 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]", "")

当使用正则表达式语法指定时,Java 6 无法识别代理对,因此正则表达式可以识别\\ud800作为一个字符并尝试编译范围\\udc00-\\udbff失败的地方。我们很幸运,它会为此输入抛出异常;否则,错误将无法被检测到。 Java 7 正确解析此正则表达式并编译为与上面相同的结构。


从 Java 7 及更高版本开始,语法\x{h..h}已添加支持指定 BMP(基本多语言平面)之外的字符,并且推荐使用它来指定星体平面中的字符。

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

该正则表达式也编译为与上面相同的结构。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么代理 Java 正则表达式会找到连字符减号 - 的相关文章

随机推荐

  • swagger-ui.html 400 错误请求

    我已将 swagger 集成到我的 Spring Boot 项目中 所有 swagger 端点都工作正常 但是 product swagger ui html给出 400 错误 经过一些调试 我发现两个端点之间存在冲突 在我的 applic
  • Android Media Codec 视频解码

    这是我的第一个问题 如果我遗漏了什么 请告诉我 使用 Android API 16 的新媒体编解码器实现来尝试解码视频 以便我可以发送要作为纹理应用的帧 纹理部分已经完成 所以我在堆栈外的一些帮助下想出了以下代码 但在runOutputBu
  • 如何在python中修改Yolo .txt文件的值

    我想修改包含 txt 文件的文件夹 txt 文件如下所示 3 0 695312 0 523958 0 068750 0 052083 3 0 846875 0 757292 0 071875 0 031250 3 0 830469 0 71
  • 如何检查 UIWebView 是否为空

    我需要检查加载完成后的网络视图是否有任何内容 我的要求很简单 它是我页面底部的一个小网络视图条 就像广告一样 I call NSURLRequest request NSURLRequest requestWithURL adURL gWe
  • 这里的地图导航 - 留下的痕迹

    我使用 Here 地图 sdk 作为导航解决方案 到目前为止一切都很好 除了有点不方便 在导航模式下 我看到计算的路线如何在 3D 模式下围绕当前位置渲染 以及当前位置如何正确显示在地图上 在onPositionUpdated打回来 但是
  • 让 Kinect SDK 在 C++ 中与 Visual Studio 2010 配合使用

    我一直在遵循微软为使用 c 设置 Kinect SDK 所做的指南 他们创建的步骤如下 在源代码中包含 windows h 要使用 NUI API 请包含 MSR NuiApi h 位置 Program Files Microsoft Re
  • Firefox DOM解析器问题

    由于某种原因 DOMParser 为每个换行符添加了一些额外的 text 元素 n对于这个网址 http rt com Root rss http rt com Root rss 以及我尝试过的许多其他 RSS 我检查了 cnn bbc f
  • React 在没有构造函数的情况下定义状态 [重复]

    这个问题在这里已经有答案了 我见过一些 React 开发人员在没有构造函数的情况下定义状态 我喜欢这样简化代码 但是这样做安全吗 class Dog extends React Component state sound Woof retu
  • 我可以在 Play! 中使用什么 SBT 构建设置? 2 框架将包含类路径上源树中的特定资源

    我想在构建中添加一个设置 该设置将从 src 树中的某个位置复制特定文件 以便它们在开发和生产模式下的类路径上可用 我不想把它们放在public文件夹 因为我不希望它们可供下载 我不想把它们放在conf文件夹 因为我想保持配置文件的干净 例
  • 查找networkx中满足特定条件的边

    我有一个网络x有向图 http networkx github io documentation latest reference classes digraph html具有节点上的属性 并且我想找到特定节点属性不同的所有边 有没有办法自
  • MongoDB 中的批量更新/更新插入?

    是否可以在 MongoDB 中进行批量更新 更新插入 而不是插入 如果是 请指出与此相关的任何文档 Thanks 您可以使用命令行程序蒙戈进口公司它应该在你的 MongoDB bin 目录中 您需要考虑使用两个选项upsert upsert
  • 具有多线程的实体框架事务

    我有一个运行多个线程的应用程序 线程不共享 ObjectContext 每个线程都有自己的 我知道它们不是线程安全的 然而 线程都在共享事务下运行 原始线程创建一个 TransactionScope 它生成的每个线程都使用主线程上的 Tra
  • 创建 SKSpriteNode 子类的子类

    假设我想创建一堆不同类型的宇宙飞船 我想设置一个基本的宇宙飞船类 我可以用它来创建其他有细微差别的宇宙飞船 我的基类看起来像这样 BaseSpaceship h interface SpaceshipNode SKSpriteNode pr
  • 致命错误:在展开可选值时意外发现 nil [重复]

    这个问题在这里已经有答案了 我当时用的是UICollectionView在 Swift 中 但当我尝试更改单元格标签的文本时 我得到了 func collectionView collectionView UICollectionView
  • VB6中Property Set和Property Let有什么区别?

    我刚刚创建了几个Property Set方法 但它们没有编译 当我将它们更改为Property Let 一切都很好 此后我研究了文档以找出两者之间的区别Property Set and Property Let 但必须承认自己并不明智 有什
  • 如何在初始开发过程中使用 Clojure 库的本地存储库?

    我有一个关于开发 Clojure 库的问题 该问题在库开发和分发的建议工作流程中没有得到解答 如下所述 http clojure doc org articles ecosystem libraries authoring html htt
  • 使用 Rfc2898DeriveBytes 将 C# PBKDF2 转换为 PHP

    长话短说 我们在 NET 中内置了一个会员系统 我们正在将其移植到 WordPress 并且需要复制 PBKDF2 加密 以便用户无需重置密码 使用已知的散列密码 我可以使用以下代码轻松在 NET 中复制此内容 static void Ma
  • 单击数据表以过滤其他图表(dc.js)

    当我单击数据表中的一行时 我需要过滤其他图表 I did my table on pretransition function table table selectAll td dc table column on click functi
  • Visual Studio 2010 中的“抑制警告”菜单项不可用

    我正在使用Visual Studio 2010 Ultimate 似乎我无法像在VS2008中使用的方式抑制警告 我的项目是用 C 编写的 当我右键单击 错误列表 窗口中的警告时 例如 缺少公共类型的 XML 注释 我没有常用的菜单项来抑制
  • 为什么代理 Java 正则表达式会找到连字符减号 -

    我试图找出为什么 JAVA 中存在这个正则表达式 ud800 udbff udc00 udfff 用于replaceAll regexp 还将删除连字符减号以及代理字符 这个的 Unicode 是 u002d所以它似乎不在任何这些范围之内