1

我正在尝试获取电话已知线路号码前面的任何数字,如果它们存在(在 Perl 中)。不会有破折号,只有数字。

例如,假设我知道行号将始终为 8675309。8675309 可能有也可能没有前导数字,如果我想捕获它们。前导数字的数量并没有真正的限制。

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

/8675309$/这将匹配如何在一个正则表达式中捕获前数字?

4

6 回答 6

9

一些正则表达式向后比向前更好。因此,有时使用 sexeger 而不是正则表达式很有用。

my $pn = '18008675309';

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

正则表达式更简洁,并且通过反转输入和捕获的值来避免大量的回溯,但代价是一些愚蠢的。

在这种情况下,回溯增益比使用通用电话号码提取正则表达式时要小:

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

有一整类问题可以使用这种技术。有关更多信息,请参阅Perlmonks 上的 sexeger 帖子

于 2010-01-14T16:00:40.813 回答
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) = "";
于 2010-01-14T15:47:49.780 回答
1

正则表达式特殊变量 $` 和 $& 是获取这些信息的另一种方式。它们分别保存匹配之前的数据内容和匹配本身。

   if ( /8675309$/ )
      {
      printf( "%s,%s,%s\n", $_, $`, $& );
      }
   else
      {
      printf( "%s,Not a match\n", $_ );
      }
于 2010-01-14T16:15:48.210 回答
1

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

它被称为 Number::Phone,代码位于 cpan.org 网站的某个位置。

于 2011-10-28T07:41:39.870 回答
0

怎么样/(\d)?(8675309)/?更新:

哎呀,应该是/(\d*)(8675309)/

于 2010-01-14T15:48:53.943 回答
0

我可能不明白这个问题。为什么第一个和第四个示例之间存在差异:

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

如果您只想将最后七位数字与其他所有数字分开,您可以这样说,而不是提供令人困惑的示例。一个正则表达式将是:

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

如果您不只是提供一个假设的数字,并且真的只是在寻找带有 '8675309' 的行(看起来很奇怪),请将 '\d{7,7}' 替换为 '8675309'。

于 2010-01-14T18:07:16.063 回答