2010-01-14 2 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

Зачем использовать регулярное выражение? Как насчет индексов() и substr() или split()? Помните http://www.codinghorror.com/blog/archives/001016.html –

+0

У вас есть пример? в perl я боюсь, что это было бы намного более беспорядочным набором вложенных ifs из-за строки переменной длины, но я мог ошибаться – user210757

+0

См. ответ hobbs на http://stackoverflow.com/questions/2055988/how-can-i- compare-international-phone-numbers-in-perl, заданный в течение последних нескольких дней. –

ответ

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

+0

@Ragepotato, мне жаль, что я не придумал этот термин. Но это незабываемо. – daotoad

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) = ""; 

выше, по крайней мере, с жемчужно-5.10-1, можно даже конденсировать до

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

мое замешательство я думал, что (\ d *) будет жадно захватить всю строку, но это не похоже. Я думал, что вам нужно делать регулярные выражения, не жадные с опцией? – user210757

+0

@unk, двигатель регулярных выражений будет возвращаться и попытаться удовлетворить условие \ d *, однако это возможно. Он начинается с захвата как можно больше, а затем отступает, когда необходимо, чтобы попытаться удовлетворить каждое последующее требование. Взгляните на выход из 'perl -Mre = debug -e '$ foo =" 18008675309 "; $ foo = ~/(\ d *) 8675309 /; '' – daotoad

0

Как насчет /(\d)?(8675309)/? UPDATE:

возгласы, который должен был haev /(\d*)(8675309)/

+1

Без якорей'^'и' $ 'этот шаблон может соответствовать в любой точке целевой строки. –

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' (кажется странным), замените '\ d {7,7}' на '8675309'.

+0

обновлено - 4-й пример должен был быть введен = '18675309' – user210757

1

Существует пакет Perl, который касается, по крайней мере, номеров телефонов Великобритании и США.

Это называется Number :: Phone и код находится где-то на сайте cpan.org.