【问题标题】:How to make capturing group optional?如何使捕获组可选?
【发布时间】:2018-05-28 06:41:06
【问题描述】:

输入

example("This is tes't")

example('This is the tes\"t')

输出应该是

This is tes't

This is the tes"t

代码

 String text = "example(\"This is tes't\")";
//String text = "$.i18nMessage('This is the tes\"t\')";
final String quoteRegex = "example.*?(\".*?\")?('.*?')?";
        Matcher matcher0 = Pattern.compile(quoteRegex).matcher(text);
        while (matcher0.find()) {
            System.out.println(matcher0.group(1));
            System.out.println(matcher0.group(2));

        }

我看到输出为

null
null

虽然当我使用正则表达式 example.*?(\".*?\") 它返回 This is tes't 而当我使用 example.*?('.*?') 它返回 This is the tes"t 但当我将两者与 example.*?(\".*?\")?('.*?')? 结合使用时,它返回 null 。为什么?

【问题讨论】:

  • 如果您打算匹配整个字符串,请使用matcher0.matches()。但是,您正在寻找类似example\\((([\"'])(?:(?!\\2).)*\\2)\\)
  • 我不明白你想在这里匹配什么。您能否向我们展示示例输入和您想要的匹配项?
  • @TimBiegeleisen 请看我的更新
  • @WiktorStribiżew 我想知道我的正则表达式中的问题,因为第一和第二个捕获组可以独立工作,但是当我将它们组合起来并使用? 使其成为可选时,它不起作用?
  • 您的正则表达式匹配like this。或者只是example,或者如果引用的刺痛紧随其后,那些被捕获的。发生这种情况是因为正则表达式末尾的所有模式都是可选的。您可能至少尝试过(\".*?\"|'.*?')

标签: java regex


【解决方案1】:

正则表达式末尾的 .*?(\".*?\")?('.*?')? 子模式序列可以匹配一个空字符串(所有 3 个部分都用匹配 0 个或多个字符的 * / *? 量化)。匹配example后,首先跳过.*?,只有在后续子模式不匹配时才会展开。但是,它们都匹配( 之前的空字符串,因此,matcher0.group(0) 中只有example

使用使第 1 组成为强制性的替代方案 (demo):

Pattern.compile("example.*?(\".*?\"|'.*?')"

或者带有缓和贪婪令牌 (demo) 的变体,可以摆脱交替:

Pattern.compile("example.*?(([\"'])(?:(?!\\2).)*\\2)"

或者,更好的是,支持转义序列 (another demo):

Pattern.compile("example.*?(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*')"

在所有 3 个示例中,您只需要访问组 1。如果在 example"' 之间只能有 (,则应将 .*? 替换为 \(,因为它会让匹配更安全。虽然,使用正则表达式来匹配字符串字面量永远不会太安全(至少,使用一个正则表达式)。

【讨论】:

    猜你喜欢
    • 2012-09-22
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    相关资源
    最近更新 更多