• Publicidad

Imprimir patrón que NO encaje con una 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.

Imprimir patrón que NO encaje con una expresión regular

Notapor JuanMan » 2008-01-19 13:39 @610

Buenas, estoy empezando con Perl y tengo una pregunta de muy muy muy novatos.

Tengo en cada línea de un fichero una hora con este formato |HH:MM| o |H:MM|. Lo que quiero conseguir es imprimir aquellas fechas que NO sean correctas (como por ejemplo: |24:00| o |9:65|).

He conseguido justo lo contrario con este código:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
while (<IN>){
    print "[$&]\n" if /[0-1]?\d:[0-5]\d/;
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


He probado a meter la exp. reg. entre corchetes y anteponerle el "^", a poner if not ... pero no consigo hacer lo que pretendo. ¿Alguien me da una idea?.

Un saludo y gracias de antemano ;).
JuanMan
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2008-01-19 13:27 @602

Publicidad

Notapor explorer » 2008-01-19 15:54 @704

Bienvenido a los foros de Perl en Español, JuanMan.

Hay un problema en la exp. reg. tuya: si analizamos las decenas de la parte de las horas, podemos pensar que puede ser 0, 1, o 2. Pero, en las unidades, podemos esperar de 0 a 9 SALVO si en las decenas tenemos un '2', que entonces esperamos un valor entre 0 y 3. Para la parte de minutos lo tenemos un poco más fácil.

Hay varias formas de solucionarlo, claro.

Lo mejor es hacerlo varias partes.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
    if ( ($h,$m) = /(\d+):(\d+)/ ) {

        print if $h > 23 or $m > 59;
    }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Queda más claro y además añades la comprobación de que la línea contiene una 'posible' hora (con el primer if).

Si aún así quieres hacerlo en una sola línea, la expresión regular es un poco más complicada de lo normal:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
while ( <IN> ) {
    print if /(\d+)(?{ $^N > 23 }):(\d+)(?{ $^R or $^N > 59 })/ and $^R;
}

 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

La expresión regular es la misma que antes (captura de dígitos con \d+) pero agregando secuencias de código ((?{})) en la que comprobamos que lo recién capturado ($^N) está dentro de los límites. El resultado de esa comprobación va quedando en la variable especial $^R. El if ejecuta primero la exp. reg. El resultado queda en $^R que quedará como verdadero si alguna de las partes está fuera de los límites. En ese caso, el 'and' evalúa la segunda parte que será cierta si $^R es cierta. Total, que el if será cierto según el valor final de $^R, indicando si sí o no es incorrecta la hora. Si es incorrecta, imprime el valor de $_.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor JuanMan » 2008-01-19 16:07 @713

Muchísimas gracias por la respuesta, has sido muy claro en tus explicaciones :D. Como bien dices, la primera es más sencilla y más intuitiva, aunque la segunda también la comprendo.

Un saludo y gracias nuevamente ;).
JuanMan
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2008-01-19 13:27 @602


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: Google [Bot] y 2 invitados

cron