2009-08-03 13 views
6

Sto scrivendo un programma minuscolo che richiede l'input dell'utente utilizzando Getops e, in base ad esso, il programma cercherà di abbinare un pattern a un testo o sostituire il testo a ciò che corrisponde.Perl qr // e sostituzione

Il problema che sto avendo è che non riesco a far funzionare la parte di sostituzione. Sto guardando la voce qr // nelle pagine man: http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators ma non ho alcuna fortuna con esso. Ho provato a modellare il mio codice esattamente come i documenti in questo caso. Compilo un modello di partita e lo sostituisco con una sostituzione.

Qualcuno potrebbe indicare dove sto andando male? (Non ti preoccupare di sicurezza troppo, questo è solo un piccolo script per uso personale)

Ecco cosa sto guardando:

if($options{r}){ 

    my $pattern = $options{r}; 
    print "\nEnter Replacement text: "; 
    my $rep_text = <STDIN>; 

    #variable grab, add flags to pattern if they exist. 
    $pattern .= 'g' if $options{g}; 
    $pattern .= 'i' if $options{i}; 
    $pattern .= 's' if $options{s}; 


    #compile that stuff 
    my $compd_pattern = qr"$pattern" or die [email protected]; 
    print $compd_pattern; #debugging 

    print "Please enter the text you wish to run the pattern on: "; 
    my $text = <STDIN>; 
    chomp $text;  

    #do work and display 
    if($text =~ s/$compd_pattern/$rep_text/){ #if the text matched or whatever 
     print $text; 
    } 
    else{ 
     print "$compd_pattern on \n\t{$text} Failed. "; 
    } 
} #end R FLAG 

Quando eseguo con -r "/ matt/"-i, e inserisci il testo sostitutivo 'matthew', sul testo 'matt', fallisce. Perchè è questo?

EDIT:

Grazie per le risposte ragazzi! E 'stato davvero molto utile. Ho combinato entrambi i tuoi suggerimenti in una soluzione funzionante al problema. Devo gestire la flag/g in modo un po 'diverso. Qui è il campione di lavoro:

if($options{r}){ 

    my $pattern = $options{r}; 
    print "\nEnter Replacement text: "; 
    my $rep_text = <STDIN>; 
    chomp $rep_text; 

    #variable grab, add flags to pattern if they exist. 

    my $pattern_flags .= 'i' if $options{i}; 
    $pattern_flags .= 's' if $options{s}; 

    print "Please enter the text you wish to run the pattern on: "; 
    my $text = <STDIN>; 
    chomp $text;  

    #do work and display 
    if($options{g}){ 
     if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/g){ #if the text matched or whatever (with the g flag) 
      print $text; 
     } 
     else{ 
      print "$pattern on \n\t{$text} Failed. "; 
     } 
    } 
    else{ 
     if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/){ #if the text matched or whatever 
      print $text; 
     } 
     else{ 
      print "$pattern on \n\t{$text} Failed. "; 
     } 
    } 
} #end R FLAG 

risposta

11

Come nota il caos, si incontreranno delle difficoltà usando qr//. Hai davvero bisogno di precompilare il modello? In caso contrario, una strategia del genere potrebbe funzionare:

my $pattern  = 'matt'; 
my $text   = 'Matt'; 
my $rep_text  = 'Matthew'; 
my $pattern_opts = 'i'; 

print $text, "\n" if $text =~ s/(?$pattern_opts:$pattern)/$rep_text/; 

Aggiornamento in risposta al vostro nuovo codice: si potrebbe considerare l'utilizzo di un approccio come questo:

my ($orig, $patt, $rep, $flags) = qw(FooFooFoo foo bar ig); 

my $make_replacement = $flags =~ s/g//  ? 
    sub { $_[0] =~ s/(?$flags:$patt)/$rep/g } : 
    sub { $_[0] =~ s/(?$flags:$patt)/$rep/ } 
; 

if ($make_replacement->($orig)){ 
    print $orig; 
} 
else { 
    print "Failed..."; 
} 
+0

Ahh, molto buono con il '(? opta: pat) '. Mi dimentico sempre che puoi farlo. – chaos

7

eseguirlo con -r "matt", non -r "/matt/". Non è necessario, e di fatto non è possibile, fornire i delimitatori del modello nella stringa di opzioni. Le virgolette sono i delimitatori nel tuo qr. Quindi è in realtà alla ricerca di matt con le barre intorno, come lo stai eseguendo, che non è quello che vuoi. Stai cercando di usare le virgolette per dire a Perl di trattare la stringa del tuo pattern come se fosse codice sorgente, ma sfortunatamente non puoi farlo.

Tutti gli schemi che si stanno facendo per le altre opzioni non funzioneranno. Dovrai cambiare il modo di compilare la regex se vuoi fare tutto questo. Qualcosa di simile potrebbe farlo per /i e /s:

my $compd_pattern = qr/$pattern/ or die [email protected]; 
$compd_pattern = qr/$compd_pattern/i if $options{i}; 
$compd_pattern = qr/$compd_pattern/s if $options{s}; 

Per /g è necessario sostenere una versione alternativa della ricerca/sostituzione. /g non è un modificatore valido per qr//.

Problemi correlati