2013-02-05 5 views
2

J'ai le code Perl suivant pour inviter l'utilisateur à répondre par oui/non. Si l'utilisateur entre autre chose que oui/non, continuez à le demander. Aucun autre mot n'est acceptable. Je ne sais pas pourquoi ce code ne fonctionne pas. J'ai testé avec la réponse "noooooo" et je m'attendais à ce qu'il invite à nouveau mais il n'entrait pas dans la boucle while.perl correspondance de chaîne exacte

Quelqu'un peut-il aider à trouver mon erreur ici?

@files = A, B, C; 

foreach $c (@files) { 
    if (-e $c ) { 
    print " $c already exists. Do you want to overwrite? (yes or no): "; 
    chomp ($file_yes_no = <STDIN>); 

    while ($file_yes_no !~ m/yes{1}|no{1}/i) { 
     print "$c already exists. Do you want to overwrite? (yes or no): "; 
     chomp ($file_yes_no = <STDIN>); 
    } 

    if ($file_yes_no =~ m/yes/i) { 
     if (system ("cp -f /home/old_path/ /home/new_path/ == 0) { 
      print "$c successfully copied; 
     } else { 
      die "Error: Copy failed, Check the message above"; 
     } 
    } 
else { print "No files copied\n; } 
+2

Utilisez 'File :: Copy' pour copier un fichier. 'utilise File :: Copy qw (copie); copy ($ src, $ dest) ou die $ !; ' – TLP

+0

que diriez-vous de' do {print ...; chomp ...} en condition; mieux encore, http://p3rl.org/IO::Prompt – ysth

+1

Utilisez-vous des avertissements d'utilisation? utiliser strict, '? – chepner

Répondre

6

Je voudrais juste utiliser l'opérateur d'égalité de chaînes eq au lieu d'une regex.

if($file_yes_no eq 'yes') ... 

Si je le voulais insensible à la casse, je voudrais tout d'abord convertir en minuscules avec lc.

Le problème avec votre regex est qu'il trouvera heureusement n'importe quelle chaîne contenant les lettres yes de manière séquentielle. Si vous le souhaitez, vous pouvez faire correspondre le début et la fin de la chaîne comme suit:

if ($file_yes_no =~ m/^yes$/i) ... 

Mais personnellement, je préfère la première option.

Oh, j'ai raté la première partie ... Hmmmm. Même chose, si vous devez utiliser regex.

m/^(yes|no)$/i 

Encore une fois, je serais plus enclin à éviter regex

+0

Merci pour la réponse. J'ai essayé avec^et $ et cela a fonctionné. J'ai essayé "ne" au lieu de! ~ Et cela n'a pas fonctionné - il saute quand même quand je réponds "nooooo" ... remarquez l'OR là dedans ... est-ce correct? while ($ file_yes_no ne "oui" || $ file_yes_no ne "non") { – NewBie

+3

Non, vous devez utiliser '&&'.La raison en est que ce ne sera * toujours * pas une chose OU pas l'autre. – paddy

+0

ah! que je suis bête! Merci! – NewBie

3

Vous devez utiliser l'expression suivante régulière Perl pour faire correspondre uniquement yes ou no (insensible à la casse):

m/^(yes|no)$/i 

Pour oui seulement , utilisez:

m/^yes$/i 
+0

utilisez '\ A' et' \ z', pas '^' et '$', ou vous ferez correspondre d'autres chaînes aussi (par exemple '' yes \ n "') – ysth

+2

@ysth, ceci correspond à une seule ligne de 'STDIN'. L'entrée multiligne ne se produira pas. –

0

Parce que vous êtes en utilisant une expression régulière. Vous pouvez écrire l'expression régulière pour correspondre au début ou à la fin de la chaîne ... comme ceci:

while($file_yes_no !~ /^(yes|no)$/) { 

Le ^ et $ sont le début et la fin de la chaîne. Aussi, vous pouvez omettre le m.

Ou vous pouvez simplement vérifier les valeurs explicitement:

while($file_yes_no ne "yes" and $file_yes_no ne "no") { 

vous avez également une faute de frappe dans votre commande système, mais je suppose qui vient de le copier ici. Vous ne devriez vraiment pas vous lancer dans un shell pour ça. Regardez dans File::Copy qui vous donne une fonction copy

+4

Vous devriez être plus prudent: '" yesss! " = ~/^ oui | non $/'est vrai. – mvp

+0

@mvp vous avez raison ... a besoin de parenthèses. Je suis à jour – Cfreak

Questions connexes