2010-01-14 7 views
1

J'essaie de saisir des chiffres devant un numéro de ligne connu d'un téléphone, s'ils existent (en Perl). Il n'y aura pas de tirets, seulement des chiffres. Par exemple, disons que je sais que le numéro de ligne sera toujours 8675309. 8675309 peut ou non avoir des chiffres principaux, si c'est le cas, je veux les capturer. Il n'y a pas vraiment de limite au nombre de chiffres principaux.Comment puis-je analyser un numéro de téléphone en Perl?

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

/8675309$/ cela correspond comment capturer le pré-chiffres dans un regex?

+2

Pourquoi utiliser regex? Qu'en est-il de index() et substr() ou split()? Rappelez-vous http://www.codinghorror.com/blog/archives/001016.html –

+0

avez-vous un exemple? en Perl je crains que ce serait beaucoup plus désordonné ensemble d'ifs imbriqués en raison de la chaîne de longueur variable, mais je pourrais avoir tort – user210757

+0

Voir la réponse de hobbs à http://stackoverflow.com/questions/2055988/how-can-i- compare-international-phone-numbers-in-perl, a demandé dans les deux derniers jours. –

Répondre

9

Certains regexes fonctionnent mieux en arrière que vers l'avant. Il est donc parfois utile d'utiliser sexeger, plutôt que regexes.

my $pn = '18008675309'; 

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

Le regex est plus propre et évite beaucoup de dos suivi au prix de certains fummery avec inversion de l'entrée et les valeurs capturées.

Le gain de retours en arrière est plus petit dans ce cas que ce serait si vous aviez une extraction de numéro de téléphone général regex:

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

Il y a une classe de problèmes où cette technique est utile. Pour plus d'informations, voir the sexeger post on Perlmonks.

+2

+1 pour "sexeger" – Ragepotato

+0

@Ragepotato, je souhaite avoir inventé le terme. Mais c'est mémorable. – daotoad

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

Le * quantificateur est gourmand mais cela signifie qu'il correspond autant que possible tout en permettant un match. Donc au début, oui, \d* essaye d'engloutir tous les chiffres dans $number, mais il abandonne à contrecœur caractère par caractère ce qu'il a apparié jusqu'à ce que le motif entier corresponde avec succès.

Une autre approche consiste à couper la queue:

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

Vous pouvez faire la même chose sans utiliser une expression régulière:

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

ci-dessus, au moins avec perl-5.10-1, pourrait même être condensé à

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

ma confusion est que je pensais que le (\ d *) aurait avidement capturé toute la chaîne, mais il ne semble pas. Je pensais que tu devais faire des regexes non gourmandes avec une option? – user210757

+0

@unk, le moteur regex va revenir en arrière et essayer de satisfaire la condition \ d *, cependant possible. Il commence par saisir autant que possible, puis recule au besoin pour essayer de satisfaire chaque exigence ultérieure. Jetez un oeil à la sortie de 'perl -Mre = debug -e '$ foo =" 18008675309 "; $ foo = ~/(\ d *) 8675309 /; '' – daotoad

0

Que diriez-vous de /(\d)?(8675309)/? MISE À JOUR:

whoops qui devrait haev été /(\d*)(8675309)/

+1

Sans les ancres'^'et' $ ', ce modèle peut correspondre n'importe où dans la chaîne cible. –

1

Les variables spéciales regex $ `et $ & sont une autre façon de saisir ces informations. Ils contiennent le contenu des données précédant le match et le match lui-même respectivement.

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

Je ne comprends peut-être pas le problème. Pourquoi est-il une différence entre les premier et quatrième exemples:

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

Si tout ce que vous voulez est de séparer les sept derniers chiffres de tout le reste, vous auriez pu dire de cette façon plutôt que de fournir des exemples de confusion .Une regex pour ce serait:

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

Si vous non seulement fournir un nombre hypothétique, et sont vraiment ne cherchez que des lignes avec '8675309' (cela semble étrange), remplacez le '\ d {7,7}' par '8675309'.

+0

mis à jour - 4ème exemple aurait dû être input = '18675309' – user210757

1

Il existe un package Perl qui traite au moins les numéros de téléphone britanniques et américains.

Cela s'appelle Number :: Phone et le code est quelque part sur le site cpan.org.

Questions connexes