cómo incluir grep en una expresión regular en perl

así que actualmente estoy atascado en este problema: 1. Declaro una lista constante, digamos LISTA 2. Quiero leer un archivo, lo cual hago línea por línea en un ciclo while, y si la línea tiene una palabra clave de LISTA, imprimo la línea, o algo así con ella.

esto es lo que tengo actualmente:

use constant LIST => ('keyword1', 'keyword2', 'keyword3');
sub main{
    unless(open(MYFILE, $file_read)){die "Error\n"};
    while(<MYFILE>){
        my $line = $_;
        chomp($line);
        if($line =~ m//){#here is where i'm stuck, i want is if $line has either of the keywords
            print $line;
        }
    }
}

¿Qué debo hacer en esa declaración if para que coincida con lo que quiero que haga el programa? y puedo hacerlo sin tener el $line variable y simplemente usando $_? solo usé $line porque pensé que grep colocaría automáticamente las constantes en LIST en $_. ¡Gracias!

preguntado el 10 de septiembre de 13 a las 01:09

1 Respuestas

La forma más fácil es definir un expresión regular citada como su constante en lugar de una lista:

use strict;
use warnings;
use autodie;    # Will kill program on bad opens, closes, and writes
use feature qw(say);   # Better than "print" in most situations

use constant {
   LIST => qr/keyword1|keyword2|keyword3/, # Now a regular expression.
   FILE_READ => 'file.txt', # You're defining constants, make this one too.
};

open my $read_fh, "<", FILE_READ;  # Use scalars for file handles

# This isn't Java. You don't have to define "main" subroutine

while ( my $line = <$read_fh> ) {
    chomp $line;
    if ( $line =~ LIST ) {  #Now I can use the constant as a regex
        say $line;
    }
}
close $read_fh;

Por cierto, si no usas Autodie, la forma estándar de abrir un archivo y fallar si no se abre es usar el or sintaxis:

open my $fh, "<", $file_name or die qq(Can't open file "$file_name": $!);

Si tiene que usar una lista como una constante, entonces puede usar join para hacer la expresión regular:

use constant LIST => qw( keyword1 keyword2 keyword3 );

...

my $regex = join "|", map LIST;
while ( my $line = <$file_fh> ) {
    chomp $line;
    if ( $line =~ /$regex/ ) {
        say $line;
    }
}

El join toma una lista (en este caso, una lista constante) y separa cada miembro por la cadena o el carácter que le asigna. Espero que sus palabras clave no contengan caracteres especiales de expresiones regulares. De lo contrario, necesita cotización inicial esos caracteres especiales.


Apéndice

mi $regex = unir '|' => mapa +quotemeta, LISTA; – Zaid

Gracias Zaid. yo no sabía sobre el quotemeta mando antes. Había estado probando varias cosas con \Q y \E, pero empezó a ser demasiado complejo.

Otra forma de hacer lo que hizo Zaid:

my @list = map { quotemeta } LIST;
my $regex = join "|", @list;

El mapa es un poco difícil de entender para los principiantes. map toma cada elemento en LIST y ejecuta el cita orden en su contra. esto vuelve -- que asigno a @list.

Imagine:

use constant LIST => qw( periods.are special.characters in.regular.expressions );

Cuando corro:

my @list = map { quotemeta } LIST;

Esto devuelve la lista:

my @list = ( "periods\.are", "special\.characters", "in\.regular\.expressions" );

Ahora, los puntos son puntos literales en lugar de caracteres especiales en la expresión regular. Cuando corro:

my $regex = join "|", @list;

Yo obtengo:

$regex = "periods\.are|special\.characters|in\.regular\.expressions";

Y esa es una expresión regular válida.

Respondido el 20 de junio de 20 a las 10:06

@Zaid No sabía sobre el quotemeta mando antes. Eso funciona muy bien. - David W.

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.