代码大致说“你应该用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
然后,由于这是由字符集主导的,我将按字符集进行空格。
/^
\+ [[: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
现在您可以开始看到一些类似的元素。尝试排列它们以查看相似之处。
/^
\+ [[: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
然后在一个元素上归零并尝试找出它。这是重要的,[0-9.[:space:]-]* 意思是“零个或多个数字、空格、破折号或圆点”。这对于电话解析没有多大意义,也许在上下文中会更有意义。让我们看一行我们可以猜出它试图做什么。
( \( [0-9.[:space:]-]* [0-9] [0-9.[:space:]-]* \) )?
- 打开括号。
- 零个或多个数字、空格、破折号或圆点。
- 一个数字
- 零个或多个数字、空格、破折号或圆点。
- 关闭括号。
括号表明这是试图解析区号。其余的将其限制为任意数量的数字、空格、破折号或圆点,但[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;
如果您对电话号码有所了解,是这样的:
- 强制性国家代码(必须以 + 和数字开头)
- 可选区号
- 可选电话号码
- 可选扩展
这个正则表达式不能很好地验证电话号码。根据这个正则表达式,“+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;