Pregunta

Estoy escribiendo un pequeño programa que toma la entrada del usuario usando Getops, y en base a ello, el programa intentará hacer coincidir un patrón con algún texto o sustituirá el texto por el que coincida.

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

¿Podría alguien señalarme dónde me estoy equivocando? (No se preocupe demasiado por la seguridad, este es solo 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 $@;
    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 lo ejecuto con -r " / matt / " -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 funcional al 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
¿Fue útil?

Solución

Como señala el caos, encontrará algunas dificultades al usar qr // . ¿Realmente necesitas precompilar el patrón? Si no, una estrategia como esta 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/;

Actualice en respuesta a su nuevo código : puede considerar usar un enfoque como este:

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

my $make_replacement = $flags =~ s/g//        ?
    sub { 

Como señala el caos, encontrará algunas dificultades al usar qr // . ¿Realmente necesitas precompilar el patrón? Si no, una estrategia como esta 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/;

Actualice en respuesta a su nuevo código : puede considerar usar un enfoque como este:

<*>[0] =~ s/(?$flags:$patt)/$rep/g } : sub {

Como señala el caos, encontrará algunas dificultades al usar qr // . ¿Realmente necesitas precompilar el patrón? Si no, una estrategia como esta 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/;

Actualice en respuesta a su nuevo código : puede considerar usar un enfoque como este:

<*>[0] =~ s/(?$flags:$patt)/$rep/ } ; if ( $make_replacement->($orig) ){ print $orig; } else { print "Failed..."; }

Otros consejos

Ejecútelo con -r " matt " , no con -r " / matt / " . No es necesario, y de hecho no puede, proporcionar delimitadores de patrón en su cadena de opciones. Las comillas son los delimitadores en su qr . Por lo tanto, en realidad está buscando matt con barras alrededor, la forma en que lo está ejecutando, que no es lo que desea. Estás tratando de usar las comillas para decirle a Perl que trate la cadena de tu patrón como si fuera un código fuente, pero desafortunadamente no puedes hacer eso.

Todos esos patrones anexan que está haciendo para las otras 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 para / i y / s :

my $compd_pattern = qr/$pattern/ or die $@;
$compd_pattern = qr/$compd_pattern/i if $options{i};
$compd_pattern = qr/$compd_pattern/s if $options{s};

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top