Re: Duda de Perl->regexp
> Hola listeros,
Hola listera!
> Ando muy entretenida ;-) parseando unos bonitos logs ;-) y tengo un
> problema que seguro que es la tontería más grande del mundo.
>
> Tengo una expresión regular y necesito que haga un poco más:
A ver, a machetearle un poco...
> (...)
> # Esto es lo que necesito que me encuentre:
> # La línea debe empezar por el contenido de la variable $id.
> $line = ~/^\$id\|.*?\|.*?\|.*?\|.*?\|.*?\|(.*?.)\|.*/;
> #####################################################
> # ~~~~~ Cómo escribo esto????
> #####################################################
Primero que nada, tu duda: Puedes poner una variable dentro de una
expresión regular sin sintaxis especial alguna - La expresión regular la
interpola como si fueran comillas dobles. Corrijo el operador que usas,
además: Estás dándole $line = ~/(...), cuando el operador correcto es =~
Lo que tú estás haciendo puede ser alguna expresión idiomática rara (y
Perl la ve como válida, pero entiendo que está haciendo una asignación por
ahí)... Pero por legibilidad y mantenibilidad (?) futura, te sugiero usar
=~
$line =~ /^$id\|.*?\|.*?\|.*?\|.*?\|.*?\|(.*?.)\|.*/;
Ahora, te sugiero modificar esto en pro de la legibilidad. Vamos por
partes:
- En cada elemento de tu línea de bitácora, basta con que preguntes por
.*, la interrogación que le estás poniendo es supérflua. Si no me
equivoco, en el sexto que tomas, necesitas que en vez de cero o más
caracteres capture uno o más, ¿cierto? En vez de hacer .*. puedes darle
.+
$line =~ /^$id\|.*\|.*\|.*\|.*\|.*\|(.+)\|.*/;
- Estás buscando un patrón .*\| cinco veces. ¿Por qué no usar un
cuantificador? Si usas (.*\|){5} queda más legible.
Ahora, yo a esto le agrego, por velocidad (y porque no estoy seguro del
comportamiento de los paréntesis de captura con un cuantificador) un ?:
al principio de este sub-patrón, para que use estos paréntesis para
agrupar únicamente, y no para capturar. Quedamos entonces con:
$line =~ /^$id\|(?:.*\|){5}(.+)\|.*/;
- ¿Te importa lo que ocurra después de encontrar a tu $encontrado? No
creo... Pero se lo estás exigiendo a Perl. Sí, le estás exigiendo algo
muy simple, pero no lo requieres. Va, pues, para afuera:
$line =~ /^$id\|(?:.*\|){5}(.+)\|/;
- Legibilidad, importante, muy importante. Por lo que dices, tú no eres
experta en expresiones regulares, y no sabes quién va a darle
mantenimiento en un futuro - Usa el modificador /x, y comenta tu
expresión. Este modificador te permite meter espacio en blanco y
comentarios sin que afecten a la expresión:
$line =~ /^$id\| # Que inicie con el identificador
(?:.*\|){5} # Cinco campos que no me importan
(.+)\| # De acá estoy tomando $encontrado
/x;
¿Te gusta más así? ;-)
> $encontrado = $+ ;
Es ligeramente más rápido y más claro usar $1 (explicitar que es el primer
caso encontrado exitosamente) a usar $+ (el siguiente - en este caso, el
primero).
> if($encontrado){
> print $encontrado, "\n";
> }
¿Vas a seguir usando $encontrado después de aquí? Si no, ¿por qué no
evitarte la creación de la variable?
...Además, se nota que vienes de C ;-) Yo pondría esto directamente
después de tu expresión en vez de todo lo que pusiste:
print "$1\n" if $1;
> Estoy empezando tanto con Perl como con las regexp y me cuesta un poco.
> Gracias por vuestro tiempo :-)
Asómate a perldoc perlre, tiene TODO lo que quieras saber al respecto.
Saludos,
--
Gunnar Wolf - gwolf@campus.iztacala.unam.mx - (+52-55)5623-1118
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF
Reply to: