• Publicidad

Problemas con expresión regular

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Problemas con expresión regular

Notapor rochi » 2007-04-23 02:13 @134

Hola tengo que reconocer el siguiente patrón en un texto que viene en un archivo .txt. El patrón es la frase que comience en una nueva línea con "En los concursos .." (espacio en blanco después de 'concursos') y finalice con "." o ":". Esta frase puede ocupar más de una línea, ya que el "." podría encontrarse en la línea siguiente.
Este es el código, no sé qué hago mal porque solo despliega una oración, y no todas las que hay.

Gracias por cualquier sugerencia, aquí va el código.

Saludos.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$er_concursos = '^En los concursos\s.*(:|\.)';

if(scalar(@ARGV)>0)  # Compruebo que haya archivos
{

    foreach $file (@ARGV)  # Busca en todos los archivos
        {
            if(open(INFILE,$file))
                {
                       $file_aux = "";
                        while ($linea = <INFILE>)
                        {
                 $file_aux = $file_aux.$linea;   # Leemos todas las líneas y las metemos en una variable
                        }
                       close (INFILE);

                        print $er_concursos if ($file_aux =~ /$er_concursos/gsm)
                 }
                 else
                     {print "No se pudo abrir archivo $file\n";}
     }
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
rochi
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-04-23 02:03 @127

Publicidad

Notapor explorer » 2007-04-23 03:15 @177

Bienvenido a los foros de Perl en Español.

El problema es el comodín glotón. Y que hay que pintar lo encontrado, no la expresión regular. Y repetir el proceso a lo largo de todo el fichero.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$er_concursos = qr/^(En los concursos\s.*?(:|\.))/ms;

local $/ = undef;

foreach $file (@ARGV) {             # Busca en todos los archivos
    open(INFILE,$file)
        or  print "No se pudo abrir archivo $file\n"
        and next;

    $file_aux = <INFILE>;           # Leemos todas las líneas y las metemos en una variable

    close INFILE;

    while ( $file_aux =~ /$er_concursos/g ) {
        print "$1\n";
    }
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Aunque no lo he probado, es básicamente lo que tenías hecho, con los siguientes cambios:
* Por notación y mejora de velocidad, $er_concursos la definimos como una expresión regular, no un string. Así la interpolación de la expresión regular se hace una sola vez en el programa y no una vez por cada ciclo.
* Indefinimos la variable $/ para que leamos todo el fichero en una única operación de lectura.
* Hacemos un bucle while con la expresión regular, para que nos dé todas las coincidencias posibles (con la ayuda de la opción /g) del patrón dentro del fichero.
* El cambio realizado en la expresión regular es colocar un '?' detrás de un comodín glotón (.*). De esta manera se queda con el patrón más corto que encuentre, no el más largo. Además se han colocado paréntesis de captura que nos devolverá nuestra frase en la variable $1.
Última edición por explorer el 2007-04-23 18:55 @830, editado 1 vez en total
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor rochi » 2007-04-23 16:04 @711

Hola, me auto respondo. Era sustituir
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
if ($file_aux =~ /$er_concursos/gsm)
            {
             print $1; print$2;
             #print "\n";
            }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

por
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
while ($file_aux =~ /$er_concursos/gsm)
            {
             print $1; print$2;
             #print "\n";
            }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Aún me entrevera el uso de /m y /s, cosas de novata.
Saludos
rochi
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-04-23 02:03 @127

Notapor rochi » 2007-04-23 16:35 @733

Por notación y mejora de velocidad, $er_concursos la definimos como una expresión regular, no un string. Así la interpolación de la expresión regular se hace una sola vez en el programa y no una vez por cada ciclo
¿Me podrias decir, o quien pueda responder, el concepto de interpolar?, no entendi demasiado.
Disculpen la pregunta, pero a medida que hago las cosas voy aprendiendo, saludos, y gracias una vez más.
rochi
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-04-23 02:03 @127

Notapor explorer » 2007-04-23 18:02 @793

Con lo de "interpolar" se refiere a que obtenemos el valor almacenado dentro de una variable o expresión, de forma 'indirecta'.

Ejemplo: si en la variable $casa tenemos el valor 'La casa de la abuela', cuando hacemos
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$casa = $casa . ' es azul.';
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

no estamos interpolando el valor almacenado en la variable. Sólo estamos haciendo una operación con ella (concatenar cadenas de caracteres). En cambio, si hacemos
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
print "$casa es azul.";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

entonces decimos que, con la ayuda de las comillas dobles, estamos 'interpolando' (haciendo aparecer) el valor de la variable $casa dentro de toda la cadena de caracteres que están entrecomilladas.

Más información en man perlop, sección Quote and Quote-like Operators.
Última edición por explorer el 2007-04-23 18:37 @817, editado 1 vez en total
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor rochi » 2007-04-23 18:24 @808

clarísimo, gracias
rochi
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-04-23 02:03 @127

Notapor explorer » 2007-04-23 18:57 @831

Ya está arreglado mi ejemplo. Había que cambiar la posición de la opción /g.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor explorer » 2007-04-23 19:08 @839

rochi escribiste:Aún me entrevera el uso de /m y /s, cosas de novata.
Las últimas recomendaciones sobre buenas prácticas en Perl recomiendan que siempre se use la combinación de opciones /xms, pues engloban las opciones más comunes para la mayor parte de las situaciones y más fáciles de entender por los nuevos programadores:
* /x : Se permite el uso del espacio en blanco para separar partes de la expresión regular.
* /m : Cambia el significado de '^' y '$'. En lugar de principio y fin del string se refieren a principio y fin de cada línea dentro de todo el string.
* /s : El comodín '.' puede localizar caracteres "\n". Que es lo mismo que decir que trata a todo el string como una sola línea.

Más información, en perlre.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor rochi » 2007-04-23 20:34 @899

Sigo con las expresiones regulares. Ahora debo filtrar aquellos nombres completos que comiencen con P y terminen en z.

Como Pablo Gomez, Pablo Sasz, Paz Ada Rodriguez, por ejemplo.
Por eso los siguientes nombres serían válidos:
Código: Seleccionar todo
Susana Gonzalez
Ema Sanchez
lucia rodriguez
Virginia Olague
Pirez Corrales


(Todos los nombres terminan con \n)

El tema es que con la expresión regular de abajo no toma Pirez Corrales, porque al estar Pirez rechaza al resto. O sea creo que estoy filtrando de más, porque Paz Ada Rodriguez lo filtra, pero debe ser por la palabra Paz.

Parte del código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$expreg_nom = '([Nn]+[Oo]+[Mm]+[Bb]+[Rr]+[Ee]+ = )([^Pp](\w*|\s*)*[^Zz])(\n)';

  while ( $file_aux =~ /$expreg_nom/gm )
            {
               print "$2\n";
            }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Saludos, graciasssss
rochi
Perlero nuevo
Perlero nuevo
 
Mensajes: 19
Registrado: 2007-04-23 02:03 @127

Notapor explorer » 2007-04-24 04:29 @228

Para evitar tener que poner mayúsculas y minúsculas, usa la opción /i en la expresión regular.

Y en cuanto a la expresión regular... me parece que la has hecho demasiado complicada. Te aconsejo que la escribas tal cual has descrito el filtro.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Siguiente

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados