• Publicidad

Problema con una expresión reg., va si leo el fichero antes

Así que programas sin strict y las expresiones regulares son otro modo de hablar. Aquí encontrarás respuestas de nivel avanzado, no recomendable para los débiles de corazón.

Problema con una expresión reg., va si leo el fichero antes

Notapor julmito » 2009-01-22 11:24 @516

Hola, estoy intentando extraer unas cadenas de unos ficheros.

La cuestión es que si cargo el contenido del fichero en una variable y extraigo las cadenas funciona bien, pero si leo línea a línea y aplico la expresión regular no va bien.

El fichero tiene esta estructura:
Código: Seleccionar todo
$otraslineas
INCLU / nombref
$$$$$$INCLU / nombref2
INCLU / nombre3
mas lineas


Quiero obtener nombref, nombref3; las que tienen $INCLU son comentarios. Mi expr. regular es:
[^\$]*INCLU \/ (.*)

Lo hago de esta forma:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open(F, "fichero");
while ($linea=(<F>)) { #Cargarlo a una variable
    $alm.=$linea;
}
while ($alm=~ s/[^\$]*INCLU \/ (.*)//m) { #Ir extrayendo cadenas y eliminandolo de la cadena
    print ":::::::::::$1:::::::::";
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Y funciona perfecto, me extrae nombref y nombre3.

El problema es que no quiero leer todo el fichero a una variable, hago algo como esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open(F, "aaa");
while ($linea=<F>) {
    while ($linea=~ s/[^\$]*INCLU \/ (.*)//m) {
        print ":::::::::::::$1:::::::::::";
    }
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Aquí esta el problema: ¿por qué de esta forma también obtengo las líneas comentadas? Es decir nombref1, nombref2 y nombref3.

Muchas gracias por cualquier idea.
julmito
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2008-11-07 06:02 @293
Ubicación: Valladolid

Publicidad

Notapor explorer » 2009-01-22 18:51 @827

La expresión regular está mal: el operador avaricioso '*' concuerda también con no concordar con nada, por lo que también es válido en las líneas en las que comienza por '$'.

Si lo que quieres es quedarte con los casos en los que la línea empieza por 'INCLU', entonces usa:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open (F, "aaa");
while ( $linea = <F> ) {
    if ($linea =~ m{^INCLU / (.+)}) {
        print ":::::::::::::$1:::::::::::";
    }
}
close F;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
que quiere decir que estamos buscando INCLU / al principio de la línea (^), y nos quedamos con lo que sigue.

(He supuesto que hay un espacio en blanco justo detrás de '/'. Si es variable el número de espacios en blanco, usar '\s*')
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor julmito » 2009-01-22 19:23 @849

Hola explorer, gracias por la respuesta.

Entiendo lo que me quieres decir... lo probaré a ver si funciona de esa manera. Además, cambiando la sustitución, porque realmente no utilizaba la cadena sustituida.

Interesante lo del ^. Sí lo conocía al igual que $ para el final pero no encontraba cómo usarlo, si la $linea contiene: $linea='INCLU / fichero.inc\nINCLU / fichero2.inc";, ¿el ^ funcionará con ambas cadenas? ¿solo con la primera? Me gustaría encontrar una expresión regular que funcione en los dos casos, cuando se lee línea a línea del fichero (open (F, "aaa"); while ( $linea = <F> ) { ..) y cuando leo el fichero a una variable y utilizo la variable, no sé si me explico.

Mañana contesto si me funciona. Gracias de nuevo.

Saludos
julmito
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2008-11-07 06:02 @293
Ubicación: Valladolid

Notapor explorer » 2009-01-22 19:58 @874

Si quieres que funcione en ambos casos, la expresión regular es esta:

^INCLU / (.+?)$

Es decir: aumentamos el control de dónde queremos que termine la captura en $1. Para eso, cambiamos el operador 'avaricioso' (.+) por un 'mínimo' (.+?). Y el punto de parada será el final de línea ($).

Esto es necesario, porque en el texto aparecen varias líneas, y el operador avaricioso podría saltar y capturar más de una línea.

Ahora bien, la forma de usarla en cada caso es distinta:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open F, "<kk.txt";
my $linea;
while (<F>) {
    if ( m{^INCLU / (.+?)$} ) {
        print "$1\n";
    }
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
open F, "<kk.txt";
my $linea;
while (<F>) {
    $linea .= $_;
}

while ($linea =~ m{^INCLU / (.+?)$}smg) {
    print "$1\n";
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En el segundo caso hacemos un bucle por toda la $linea, mientras (while) existan patrones reconocibles (la exp. reg.). Para ello usamos la opción 'g', como repetición de búsqueda, hasta el final. E indicamos que ^ y $ se refieren a líneas contenidas dentro de una cadena de caracteres mayor, con la ayuda de s y m (realmente, solo nos hace falta m -múltiples líneas-).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor julmito » 2009-01-23 03:44 @197

Hola de nuevo explorer; me ha sorprendido la rapidez de tu respuesta, y lo perfecta que es. Solo me queda felicitarte y comprender.

Funciona correctamente. Me había empeñado en indicar [QUE NO HAYA $] en vez de darle la vuelta de esa forma ^ línea nueva. Ademas ahora mirare las opciones de la expresión regular (smg), sospecho que la g será que vaya aplicando varias veces la expresion... bueno, ahora lo miro.

Te agradezco tu ayuda y rapidez. Gracias nuevamente.

Un saludo
julmito
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2008-11-07 06:02 @293
Ubicación: Valladolid


Volver a Avanzado

¿Quién está conectado?

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

cron