2010-01-14 93 views
1

我想抓住手机已知行号前面的任何数字,如果它们存在(在Perl中)。不会有破折号,只有数字。如何在Perl中解析电话号码?

例如,假设我知道行号始终为8675309. 8675309可能有也可能没有前导数字,如果是的话我想捕获它们。前几位的数字没有限制。

$input   $digits  $number 
'8675309'  ''   '8675309' 
'8008675309' '800'   '8675309' 
'18888675309' '1888'  '8675309' 
'18675309'  '1'   '8675309' 
'86753091'  not a match 

/8675309$/这将匹配如何捕获一个正则表达式中的前几位?

+2

为什么使用正则表达式?怎么样index()和substr()或split()?请记住http://www.codinghorror.com/blog/archives/001016.html – 2010-01-14 15:59:16

+0

你有没有例子?在perl恐怕这将是更混乱的嵌套ifs由于可变长度字符串,但我可能是错误的设置 – user210757 2010-01-14 16:14:06

+0

请参阅hobbs的答案http://stackoverflow.com/questions/2055988/how-cani-i-比较国际电话号码在perl,在过去几天问。 – 2010-01-14 18:58:02

回答

9

一些正则表达式比前锋更好地工作倒退。所以有时使用sexeger而不是正则表达式会很有用。

my $pn = '18008675309'; 

reverse($pn) =~ /^9035768(\d*)/; 
my $got = reverse $1; 

的正则表达式是清洁,避免了很多回一些fummery与颠倒输入和捕获的值的成本跟踪。

回溯增益在这种情况下小于这将是如果你有一个普通的电话号码提取的正则表达式:

Regex: /^(\d*)\d{7}$/ 
Sexeger: /^\d{7}(\d*)/ 

这里有一整类问题,其中这种技术是非常有用的。欲了解更多信息,请参阅the sexeger post on Perlmonks

+2

+1“sexeger” – Ragepotato 2010-01-14 18:09:14

+0

@Ragepotato,我希望我发明了这个词。但它是令人难忘的。 – daotoad 2010-01-14 20:05:35

2
my($digits,$number); 
if ($input =~ /^(\d*)(8675309)$/) { 
    ($digits,$number) = ($1,$2); 
} 

*量词是贪婪的,但这就意味着它尽可能相匹配,同时还允许匹配。所以最初,是的,\d*试图吞噬$number中的所有数字,但它不情愿地放弃逐字符的匹配,直到整个模式匹配成功。

另一种方法是砍掉尾部:

(my $digits = $input) =~ s/8675309$//; 

你可以做同样的,而无需使用一个正则表达式:

my $digits = $input; 
substr($digits, -7) = ""; 

上面,至少用Perl-5.10-1,甚至可以压缩到

substr(my $digits = $input, -7) = ""; 
+0

我的困惑是我认为(\ d *)会贪婪地捕获整个字符串,但它似乎并不如此。我以为你必须让正则表达式不贪婪的选项? – user210757 2010-01-14 15:51:47

+0

@unk,正则表达式引擎会回溯并尽可能地满足\ d *条件。它首先尽可能地抓住,然后根据需要退出,以满足后续的各项要求。看看'perl -Mre = debug -e'$ foo =“18008675309”的输出; $ foo =〜/(\ d *)8675309 /;'' – daotoad 2010-01-14 20:18:49

0

/(\d)?(8675309)/怎么样? UPDATE:

哎呦应该haev一直/(\d*)(8675309)/

+1

没有'^'和'$'锚点,该模式可以匹配目标字符串中的任何位置。 – 2010-01-14 18:11:55

1

正则表达式特殊变量$`和$ &是抓取这些信息的另一种方式。他们分别持有比赛前数据的内容和比赛本身。

if (/8675309$/) 
     { 
     printf("%s,%s,%s\n", $_, $`, $&); 
     } 
    else 
     { 
     printf("%s,Not a match\n", $_); 
     } 
0

我可能不明白的问题。为什么会出现在第一和第四实例之间的区别:

'8675309' '' '8675309' 
... 
'8675309' '1' '8675309' 

如果你想要的是从一切最后七位数字分开,你可能会说这种方式,而不是提供混乱的例子。一种是正则表达式是:

/(\ d *)(\ d {7,7})$/

如果你不只是提供了一个假设数目,真的是只用'8675309'(看起来很奇怪)寻找线条,用'8675309'替换'\ d {7,7}'。

+0

已更新 - 应该输入第四个示例='18675309' – user210757 2010-01-15 18:30:43

1

有一个Perl包,至少处理英国和美国的电话号码。

它被称为Number :: Phone,代码位于cpan.org站点上的某处。