【问题标题】:Java String replace - non-capturing group capturesJava String replace - 非捕获组捕获
【发布时间】:2019-12-31 01:11:24
【问题描述】:

我有以下 Java 代码:

String initial = "Phone number: [194-582-9412]";
System.out.println(initial.replaceAll("\\d{3}\\-\\d{3}(?=\\-\\d{4})","XXX-XXX"));
System.out.println(initial.replaceAll("\\d{3}\\-\\d{3}(?:\\-\\d{4})","XXX-XXX"));

产生输出:

电话号码:[XXX-XXX-9412]
电话号码:[XXX-XXX]

我的逻辑是找到 3 个数字、一个破折号、3 个数字(捕获到这一点)、一个破折号和四个数字(到这个点未捕获)。根据this tutorial,以?= 开头的前瞻组是非捕获的。根据the Pattern Javadoc,以?: 开头的组也是非捕获的。我希望两个正则表达式都能产生相同的输出,Phone number: [XXX-XXX-9412]。但是,带有非捕获组(?:\\-\\d{4}) 的正则表达式似乎捕获了整个电话号码并将其替换。为什么会这样?

【问题讨论】:

  • 有什么理由不只是将电话号码本身作为一个组来捕获?似乎是双重否定(替换你不想要的,而不是抓住你所做的)
  • 环视不消耗字符串中的字符。非捕获组会消耗字符串中的字符,但不会创建捕获组。了解lookaroundsgrouping and capturing
  • @Rogue 我需要在将相关数据部分发送给用户之前屏蔽电话号码(始终采用相同的格式),如果他们没有该信息的安全凭证。我只是想知道?: 在这里的奇怪行为,因为这是我想到的第一个选项,但它没有按预期工作。
  • @Thefourthbird 好的,我想我现在明白了。关于消耗字符(而不是捕获组)的那一点对我最有帮助。
  • 它没有捕获。但是您正在替换所有匹配的内容,包括非捕获组。第一个工作的原因不是因为它没有捕获,而是因为它是零宽度。

标签: java regex


【解决方案1】:

您实际上可以使用捕获组来做您想做的事情。在这里,它捕获您要保留的部分并替换整个字符串。 $1 是对捕获组的反向引用。

 System.out.println(
            initial.replaceAll("\\d{3}-\\d{3}(\\-\\d{4})", "XXX-XXX$1"));

而且我假设您意识到如果regex 不匹配,则返回原始字符串而不做任何更改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    • 2013-12-04
    • 2014-06-26
    • 1970-01-01
    • 2015-06-07
    • 2013-01-25
    • 1970-01-01
    相关资源
    最近更新 更多