Perl电话号码正则表达式

Jor*_*dan 4 regex perl

很抱歉问这么简单的问题,我还是一个没有经验的程序员.我在工作中遇到了一些旧的perl代码中的电话号码匹配正则表达式,如果有人能够准确解释它的含义(我的正则表达式技能严重缺乏),我会很高兴.

if ($value !~ /^\+[[:space:]]*[0-9][0-9.[:space:]-]*(\([0-9.[:space:]-]*[0-9][0-9.[:space:]-]*\))?([0-9.[:space:]-]*[0-9][0-9.[:space:]-]*)?([[:space:]]+ext.[0-9.[:space:]-]*[0-9][0-9.[:space:]-]*)?$/i) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

先感谢您 :)

Sch*_*ern 9

代码粗略地说"你应该用Number :: Phone替换它".

除了所有开玩笑和好建议之外,在弄清楚正则表达式时要做的第一件事就是扩展它/x.第一步是通过捕获组来解决问题.

/^
 \+[[:space:]]*[0-9][0-9.[:space:]-]*
 (\([0-9.[:space:]-]*[0-9][0-9.[:space:]-]*\))?
 ([0-9.[:space:]-]*[0-9][0-9.[:space:]-]*)?
 ([[:space:]]+ext.[0-9.[:space:]-]*[0-9][0-9.[:space:]-]*)?
$/xi
Run Code Online (Sandbox Code Playgroud)

然后,由于这是由字符集控制,我按字符集空间.

/^
 \+ [[:space:]]* [0-9] [0-9.[:space:]-]*
 ( \( [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* \) )?
 ( [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* )?
 ( [[:space:]]+ ext . [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* )?
$/xi
Run Code Online (Sandbox Code Playgroud)

现在你可以开始看到一些类似的元素了.尝试将这些内容联系起来以查看相似之处.

/^
 \+        [[:space:]]* [0-9] [0-9.[:space:]-]*
 ( \( [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* \) )?
 (    [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]*    )?
 ( [[:space:]]+ 
   ext . 
      [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* 
 )?
$/xi
Run Code Online (Sandbox Code Playgroud)

然后归零一个元素并尝试弄清楚.这是重要的一个,[0-9.[:space:]-]*意思是"零个或多个数字,空格,破折号或点".这对手机解析没有多大意义,也许它会在上下文中更有意义.让我们看看我们可以猜到它正在尝试做什么的一条线.

( \( [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* \) )?
Run Code Online (Sandbox Code Playgroud)
  • 打开paren.
  • 零个或多个数字,空格,短划线或点.
  • 一个号码
  • 零个或多个数字,空格,短划线或点.
  • 关闭paren.

parens建议这是试图解析区号.其余部分将其限制为任意数量的数字,空格,短划线或点,但[0-9]确保至少有一个数字.这可能是作者处理多种电话号码格式的方式.

让我们给它一个名字,称之为phone_chars,因为这是作者决定电话号码的原因.还有另一个元素,[0-9.[:space:]-]* [0-9] [0-9.[:space:]-]*我将其称为"电话原子",因为它是作者决定电话号码原子的原因.如果我们将它放在自己的正则表达式中并使用它构建手机正则表达式,事情会变得更加清晰.

my $phone_chars = qr{[0-9.[:space:]-]};
my $phone_atom  = qr{$phone_chars* [0-9] $phone_chars*}x;

/^
 \+ [[:space:]]* [0-9] $phone_chars*
 ( \( $phone_atom \) )?
 (    $phone_atom    )?
 ( [[:space:]]+ ext . $phone_atom )?
$/xi;
Run Code Online (Sandbox Code Playgroud)

如果你对电话号码有所了解,就像这样:

  1. 强制性国家/地区代码(必须以+和数字开头)
  2. 可选区号
  3. 可选的电话号码
  4. 可选扩展

这个正则表达式不能很好地验证电话号码.根据此正则表达式,"+ 1"是有效的电话号码,但"(555)123-4567"不是因为它没有国家/地区代码.

电话号码验证很难.我提到过Number :: Phone吗?

use strict;
use warnings;
use v5.10;

use Number::Phone;

my $number = Number::Phone->new("+1(555)456-2398");
say $number->is_valid;
Run Code Online (Sandbox Code Playgroud)


Mar*_*rty 6

令人惊讶的扩展模式,一点点空白和一些评论可以做...

if ($value !~  /
      ^                 # Anchor to start of string

     \+                 # followed (immediately) by literal '+'
     [[:space:]]*       # zero or more chars in the POSIX character class 'space'
     [0-9]              # compolsory digit
     [0-9.[:space:]-]*  # zero or more digit, full-stop, space or hyphen

     (                  # start capture to $1
         \(                   # Literal open parentheses
         [0-9.[:space:]-]*    # zero or more ... (as above)
         [0-9]                # compolsory digit
         [0-9.[:space:]-]*    # zero or more ... (as above)
         \)                   # Literal close parentheses
     )?                 # close capture to $1 - whole thing optional

     (                  # start capture to $2
         [0-9.[:space:]-]*    # zero or more ... (as above)
         [0-9]                # compolsory digit
         [0-9.[:space:]-]*    # zero or more ... (as above)
     )?                 # close capture to $2 - whole thing optional

     (                  # start capture to $3
         [[:space:]]+         # at least one space (as definned by POSIX)
         ext.                 # literal 'ext' followed by any character
         [0-9.[:space:]-]*    # zero or more ... (as above)
         [0-9]                # compolsory digit
         [0-9.[:space:]-]*    # zero or more ... (as above)
     )?                 # close capture to $3 - whole thing optional

      $                 # Anchor to end of string
              /ix       # close regex; ignore case, extended mode options
   )  {
Run Code Online (Sandbox Code Playgroud)