首页 > 解决方案 > 需要改进从 26 到 28 种不同格式的 R 正则表达式电话号码提取

问题描述

我正在尝试从 R 中 28 种不同格式的随机文本电话号码中提取。我已经阅读了以前关于 R 正则表达式的帖子,例如\被替换为\\,并使用 运行正则表达式运算符perl=TRUE,所以我已经解决了我的大部分问题。我需要一些调试方面的帮助。

我在 R 中使用以下正则表达式:

medium_regex2 = "(?:\\+?(\\d{1})?-?\\(?(\\d{3})\\)?[\\s-\\.]?)?(\\d{3})[\\s-\\.]?(\\d{4})[\\s-\\.]?"

并运行以下代码:

medium_phone_extract2 <- function(string){
  unlist(regmatches(string,gregexpr(medium_regex2,string, perl=TRUE)))
}
medium_phone_extract2(phonenumbers)

该表达式正确地指出了 28 个数字中的 26 个。两种缺失的号码格式是:“+90-555-4443322”“+1.517.3002010”

您将如何改进正则表达式以便正确提取这两种格式?

编辑:我试图提取的完整 28 种格式是:

phonenumbers <- c("05554443322",
                  "0555 444 3322",
                  "0555 444 33 22",
                  "5554443322", 
                  "555 444 3322",
                  "555 444 33 22",
                  "905554443322",
                  "+905554443322",
                  "+90-555-4443322",
                  "+1-517-3002010",
                  "+1-(800)-3002010",
                  "+1-517-3002010",
                  "+1.517.3002010",
                  "000-000-0000",
                  "000 000 0000",
                  "000.000.0000",
                  "(000)000-0000",
                  "(000)000 0000",
                  "(000)000.0000",
                  "(000) 000-0000",
                  "(000) 000 0000",
                  "(000) 000.0000",
                  "000-0000",
                  "000 0000",
                  "000.0000",
                  "0000000",
                  "0000000000",
                  "(000)0000000")
howmany_numbers <- length(phonenumbers)
#28

我能够用正则表达式提取的 26 个是:

 [1] "05554443322"      "0555 444 3322"    "5554443322"       "555 444 3322"     "90555444332"     
 [6] "+90555444332"     "0-555-4443322"    "+1-517-3002010"   "+1-(800)-3002010" "+1-517-3002010"  
[11] "517.3002010"      "000-000-0000"     "000 000 0000"     "000.000.0000"     "(000)000-0000"   
[16] "(000)000 0000"    "(000)000.0000"    "(000) 000-0000"   "(000) 000 0000"   "(000) 000.0000"  
[21] "000-0000"         "000 0000"         "000.0000"         "0000000"          "0000000000"      
[26] "(000)0000000" 

标签: rregex

解决方案


您可以使用以下正则表达式:

(?:\+?\d{0,3}-?\(?[\s.-]?\d{3}\)?[\s.-]?)?\d{3}[\s.-]?\d{2}\s?\d{2}

如果您只想在不在其他数字内时匹配它,您可以添加(?<!\d)/(?!\d)环顾四周以防止在左侧或右侧有数字时匹配:

(?<!\d)(?:\+?\d{0,3}-?\(?[\s.-]?\d{3}\)?[\s.-]?)?\d{3}[\s.-]?\d{2}\s?\d{2}(?!\d)

为确保双方通常的单词边界使用

(?<!\w)(?:\+?\d{0,3}-?\(?[\s.-]?\d{3}\)?[\s.-]?)?\d{3}[\s.-]?\d{2}\s?\d{2}\b

在 R 中,不要忘记将字符串文字中的所有反斜杠加倍:

regex <- "(?<!\\w)(?:\\+?\\d{0,3}-?\\(?[\\s.-]?\\d{3}\\)?[\\s.-]?)?\\d{3}[\\s.-]?\\d{2}\\s?\\d{2}\\b"

要点

  • ((\\d{1})?|(\\d{2})?|(\\d{3}))?最好写为\d{0,3}, 零到三位数的模式(与更线性、直接的模式相比,交替使匹配过程更消耗资源)
  • [\\s.-]首选,[\\s\\-\\.]因为连字符最好放在字符类的末尾(无需在那里转义)并注意.始终匹配.字符类中的文字
  • (\\d{4}|\\d{2}\\s\\d{2})可以并且应该重写为\\d{2}\\s?\\d{2}匹配的 2 位数字,后跟可选的空格,然后是 2 位数字。
  • 不确定您是否真的想在模式末尾匹配空格、连字符或点,所以我建议[\\s-\\.]?在末尾删除。

推荐阅读