2009-08-03 27 views
6

Estoy escribiendo un pequeño programa que requiere la entrada del usuario usando Getops, y basado en él, el programa tratará de hacer coincidir un patrón con algún texto, o sustituir el texto por el que coincida.Perl qr // y sustitución

El problema que tengo es que no puedo conseguir que la parte de sustitución funcione. Estoy mirando la entrada qr // en las páginas man: http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators pero no estoy teniendo suerte con eso. Intenté modelar mi código exactamente como los documentos en este caso. Recopilo un patrón de coincidencia y lo sustituyo en una sustitución.

¿Podría alguien señalar dónde me estoy equivocando? (No se preocupe por la seguridad demasiado, esto es sólo un pequeño script para uso personal)

Esto es lo que estoy viendo:

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 

Cuando corro con -r "/ mate/"-i, e ingrese el texto de reemplazo 'matthew', en el texto 'mate', falla. ¿Por qué es esto?

EDITAR:

Gracias por las respuestas chicos! Eso fue realmente muy útil. Combiné ambas sugerencias en una solución de trabajo para el problema. Tengo que manejar la bandera/g un poco diferente. Aquí está la muestra de trabajo:

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 

Respuesta

11

Como señala el caos, encontrará algunas dificultades al usar qr//. ¿Realmente necesitas precompilar el patrón? En caso contrario, una estrategia como esto podría funcionar:

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/; 

actualización en respuesta a su nuevo código de: es posible considerar el uso de un enfoque como este:

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, muy bueno con el '(? opts: pat) '. Siempre me olvido de que puedes hacer eso. – chaos

7

Ejecutar con -r "matt", no -r "/matt/". No necesita, y de hecho no puede, suministrar delimitadores de patrones en su cadena de opciones. Las comillas son los delimitadores en su qr. Así que en realidad está buscando matt con barras alrededor, la forma en que lo está ejecutando, que no es lo que quiere. Está tratando de usar las comillas para decirle a Perl que trate su cadena de patrones como si fuera el código fuente, pero desafortunadamente no puede hacer eso.

Todos los patrones anexos que está haciendo para las demás opciones tampoco funcionarán. Tendrá que cambiar la forma en que compila la expresión regular si desea hacer todo eso. Algo como esto podría hacerlo por /i y /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}; 

Para /g que necesita para apoyar una versión alternativa de la búsqueda/reemplazo. /g no es un modificador válido para qr//.

Cuestiones relacionadas