[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: