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