【问题标题】:Regular expression to match optional end of string正则表达式匹配字符串的可选结尾
【发布时间】:2016-09-26 22:08:01
【问题描述】:

鉴于以下情况:

"John Smith"
"John Smith (123)"
"John Smith (123) (456)"

我想捕捉:

"John Smith"
"John Smith", "123"
"John Smith (123)", "456"

什么 Java 正则表达式允许我这样做?

我试过(.+)\s\((\d+)\)$,它适用于“John Smith (123)”和“John Smith (123) (456)”,但不适用于“John Smith”。如何更改正则表达式以使其也适用于第一个输入?

【问题讨论】:

  • 你也可以贪心^([^(\r\n]+)(?:\((.*)\))?
  • @revo 似乎不起作用。在 "John Smith (123) (456)" 中,它捕获了 ""123) (456",这不是我想要的。
  • 是的,你是对的:^([^(\r\n]+$|.*(?:\((.*)\)))
  • 那也行不通。在“John Smith (123)”中,我想捕捉“John Smith”和“123”。
  • 那么你需要将.* 括在括号中。

标签: java regex


【解决方案1】:

您可以将第一个 .+ 转为惰性,并使用非捕获可选组包装后面的部分:

(.+?)(?:\s\((\d+)\))?$
   ^ ^^^           ^^ 

regex demo

实际上,如果您使用带有String#matches() 的正则表达式,最后一个$ 是多余的。

详情

  • (.+?) - 组 1 捕获除换行符之外的一个或零个字符,尽可能少(因此,允许后续子模式“落入”一个组中)
  • (?:\s\((\d+)\))? - 一个可选的空格序列,(,第 2 组捕获 1+ 个数字和一个 )
  • $ - 字符串锚点结束。

Java demo:

String[] lst = new String[] {"John Smith","John Smith (123)","John Smith (123) (456)"};
Pattern p = Pattern.compile("(.+?)(?:\\s\\((\\d+)\\))?");
for (String s: lst) {
    Matcher m = p.matcher(s);
    if (m.matches()) {
        System.out.println(m.group(1));
        if (m.group(2) != null)
            System.out.println(m.group(2));
    }
}

【讨论】:

  • 非常感谢!
猜你喜欢
  • 2015-09-28
  • 2011-09-23
  • 2021-01-17
  • 1970-01-01
  • 2016-03-26
  • 1970-01-01
  • 2015-08-01
  • 1970-01-01
相关资源
最近更新 更多