【问题标题】:Matching a phone number at the end of a string with `regex`, and return both parts将字符串末尾的电话号码与 `regex` 匹配,并返回两个部分
【发布时间】:2016-07-08 13:36:37
【问题描述】:

我有一堆类似如下的行:

Name1 Surname1         +44 (020) 1234 5678 
Name2 Name2 Surname2   +39 (051) 12.34.56
Surname3, Name3      -     (555) 123-456-789
Surname4, Name4 Name4       123 - 456.78.90

我想识别并返回它们包含的名称和数字。例如,我想返回:

  1. Name1 Surname1 +44 (020) 1234 5678
    • 姓名:Name1 Surname1
    • 号码:+44 (020) 1234 5678
  2. Name2 Name2 Surname2 +39 (051) 12.34.56
    • 姓名:Name2 Name2 Surname2
    • 号码:+39 (051) 12.34.56
  3. Surname3, Name3 - (555) 123-456-789
    • 姓名:Surname3, Name3 -
    • 号码:(555) 123-456-789
  4. Surname4, Name4 Name4 123 - 456.78.90
    • 姓名:Surname4, Name4 Name4
    • 号码:123 - 456.78.90

我正在使用 Java regex,到目前为止,我想出了以下模式:

\A(.*)\s+(\+?\s*\d+([.-\s]*(\d+|\(\d+\)))+)\z

如果line 是上述任何一行,则匹配模式的代码是:

Pattern pattern = Pattern.compile("^(.*)\\s+(\\+?\\s*\\d+([.-\\s]*(\\d+|\\(\\d+\\)))+)$");
Matcher matcher = pattern.match(line);
if (matcher.find()) {
    System.out.println("Name: " + pattern.group(1));
    System.out.println("Number: " + pattern.group(2));
}

不幸的是,在任何line(例如Name1 Surname1 +44 (020) 1234 5678)上,它都会返回以下内容:

Name: Name1 Surname1         +44 (020) 1234
Number: 5678

我认为这个结果的原因是regex 太贪心了,但我不明白如何修改它的行为。

任何人都可以更正模式并简单地向我解释解决方案吗?我阅读了一些教程,但不知道该怎么做。提前致谢!

【问题讨论】:

  • 好吧,我被@ClasG 打败了(不错),但我可以提供您自己的正则表达式的修改版本。我得到了:^(.*?)\s+(\+?\s*((\d+|\(\d+\))[-.\s]*)+)$
  • 实际上,我刚刚意识到电话号码可能只是以数字开头(添加示例 4 以反映这种情况)并且缺少匹配行尾的符号,因此正确的正则表达式应该是:^(.*?)\s*((?:\+|\(|\d)[-\d(). ]*)$,其中:^ 行首 (.*?) 匹配任何字符串的组(可能为空),但不匹配以下 \s* 一个(可能为空)分隔符 ( ... ) 另一个组,其内容为:@987654348 @ 前进直到匹配+(0..9 [ .-\d)(]* 由`, ., -, 0..9, (, ( `
  • 最后评论,我保证!我注意到在数字前加上\b 很有用:^(.*?)\s*\b((?:\+|\(|\d)[-\d(). ]+)

标签: java regex regex-greedy


【解决方案1】:

我现在能想到的最简单的是

^(.*?)\s*((?:\+|\()[-\d(). ]*)

它捕获直到+( 之前的空格的所有内容。然后它将之后的所有内容(数字、连字符、括号、点或空格)捕获到第二组。

Check it out here at regex101.

【讨论】:

  • 效果很好,谢谢!我正在查看您喜欢的网站,它提供了很好的解释。
  • 很高兴为您提供帮助。我刚刚注意到第三个示例中的连字符被捕获为名称的一部分。您可以通过使用^(.*?)[-\s]*((?:\+|\()[-\d(). ]*)$ 来避免这种情况(在各部分之间留出空格连字符。See here
  • 没关系,谢谢!我还有一些其他代码可以处理名称部分!
  • 我认为您的正则表达式也错过了最后的$(我自己无法添加)...
  • 它在第二个中(在我的评论中)。但这确实没有必要,因为最终捕获是贪婪的,它会捕获直到 EOL 的所有内容。
猜你喜欢
  • 2011-09-16
  • 1970-01-01
  • 2014-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-23
相关资源
最近更新 更多