• Publicidad

Duda 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.

Duda con expresión regular

Notapor fgalves » 2007-02-05 11:41 @528

Hola a todos

El caso es que tengo la siguiente expresión regular:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $filename_regexp = qr/^STAT_\d{8}_\d{6}(\.\w+\.\d+)?\.\d{2}\.(\d+)_(\d+)$/;
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Quiero modificarla de forma que no me agarre cadenas que terminen por 0000000000_0000000000 (correspondientes al (\d+)_(\d+)$/)
Es decir, que no me agarre cadenas que terminen por una serie de ceros, el carácter '_' y otras cadenas de ceros.

¿Hay algún modo de indicarlo directamente en la regexp?

¡¡Muchas gracias!!
Saludos,
Felipe
fgalves
Perlero nuevo
Perlero nuevo
 
Mensajes: 210
Registrado: 2006-09-25 13:54 @621

Publicidad

Notapor kidd » 2007-02-05 12:01 @542

Hola:

Podrías cambiar para que te regrese a menos de que no sean ceros, por ejemplo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $filename_regexp = qr/^STAT_\d{8}_\d{6}(\.\w+\.\d+)?\.\d{2}\.([^0]+)_([^0]+)$/;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Saludos
Uriel Lizama Perl programmer fundador de Perl en Español
Perl Programming Language
Avatar de Usuario
kidd
Creador de Perl en Español
Creador de Perl en Español
 
Mensajes: 1166
Registrado: 2003-10-15 16:52 @744
Ubicación: México

Notapor fgalves » 2007-02-06 02:29 @145

Hola kidd,

En primer lugar, muchas gracias por contestar.
Mi duda a tu propuesta es la siguiente:

Para mi, la cadena siguiente deberia ser valida:
Código: Seleccionar todo
0000000001_0000000000

o
Código: Seleccionar todo
0010002000_0020002100


El caso es que no estoy seguro pero creo que lo que propones evita completamente el cero dentro de la cadena. Yo lo unico que quiero es evitar los casos en que todos los valores son cero:
Código: Seleccionar todo
0000000000_0000000000



Si lo que propones evita conjuntos de cero como necesito, mi duda es la siguiente: que conjunto representa [^0]+? Yo solo puedo aceptar valores numericos y no se si esa expresion acepta caracteres...

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $filename_regexp = qr/^STAT_\d{8}_\d{6}(\.\w+\.\d+)?\.\d{2}\.(\d+)_(\d+)$/;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Lo que si se es que puedo extraer los valores con $2 y $3 y hacer la verificacion despues, pero queria saber si se podia hacer directamente en la expresion regular.

A continuacion tengo la siguiente instruccion:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my @files = sort(grep /$filename_regexp/, readdir(DIR));
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Si no se puede modificar la regexp para filtrar directamente los 0000_00000, como hacerlo en el grep para obtener la lista de ficheros sin los que terminen por 0000_00000? Alguien podria echarme una mano?

Muchas gracias por cualquier consejo o ayuda,
Saludos,
Felipe
fgalves
Perlero nuevo
Perlero nuevo
 
Mensajes: 210
Registrado: 2006-09-25 13:54 @621

Notapor fgalves » 2007-02-06 10:31 @480

Hola de nuevo a todos,

Al final he logrado lo que queria con el siguiente codigo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $filename_regexp = qr/^STAT_\d{8}_\d{6}(\.\w+\.\d+)?\.\d{2}\.(\d+)_(\d+)$/;

my $currfile_regexp = qr/^STAT_\d{8}_\d{6}(\.\w+\.\d+)?\.\d{2}$/;


# List all the files in the directory
    opendir(DIR,"$statDir") || die "FATAL: Could not open $statDir directory\n";

    my @files;

    # Select statistic files (including current one or not) from listed files and sort
    if ($USECURRENTFILE == 1)
    {
                @files = grep {/$filename_regexp|$currfile_regexp/ && (defined $2 ? $2 !~ /^[0]+$/:1) && (defined $3 ? $3 !~ /^[0]+$/:1) } readdir(DIR);
        @files = sort @files;
    }
    else
    {
        @files = grep {/$filename_regexp/ && $2 !~ /^[0]+$/ &&  $3 !~ /^[0]+$/} readdir(DIR);
        @files = sort @files;
    }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Que os parece? Los tests que he hecho parecen funcionar..
Gracias por adelantado!
Saludos,
Felipe
fgalves
Perlero nuevo
Perlero nuevo
 
Mensajes: 210
Registrado: 2006-09-25 13:54 @621

Notapor explorer » 2007-02-06 12:39 @569

Por lo que veo, tanto en $filename_regexp como en $currfile_regexp hay un par de paréntesis de captura, opcional, y que nunca compruebas su existencia: (\.\w+\.\d+)? por lo que suponemos que no te interesa (a lo largo del programa no compruebas el valor de $1).

Como los casos que nos interesa obviar son 'especiales' por valer "00000000000", podemos aprovechar esa circunstancia para ahorrar un poco de escritura, al poder usar el valor de verdad de un valor que es cero. Atención, "00000000000" es un valor verdadero en Perl. "0" o 0 sí que es falso en Perl.

Si suponemos que tenemos esta entrada:
Código: Seleccionar todo
STAT_12345678_123456.palabra.123.01.0010002000_0020002100
STAT_12345678_123456.palabra.123.02.0010002000_0020002100
STAT_12345678_123456.palabra.123.03.0000000000_0000000000
STAT_12345678_123456.04.0010002000_0020002100
STAT_12345678_123456.05.0000000000_0000000000
STAT_12345678_123456.palabra.123.06
STAT_12345678_123456.07
el siguiente código
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;

my $filename_regexp = qr/
    ^STAT_                  # Cabecera
    \d{8}
    _
    \d{6}
    (?:\.\w+\.\d+)?         # Parte opcional
    \.
    \d{2}
    (?:|                    # La parte final puede no existir
        \.
        (\d+)               # $1
        _
        (\d+)               # $2
    )
    $
/x;

open my $file, '<', 'kk.txt';

my @files =
    sort
        grep { /$filename_regexp/ and defined $1 and 0+$1 and defined $2 and 0+$2 }
            <$file>;

close $file;

undef $";
print "@files";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
genera la salida filtrada
Código: Seleccionar todo
STAT_12345678_123456.04.0010002000_0020002100
STAT_12345678_123456.palabra.123.01.0010002000_0020002100
STAT_12345678_123456.palabra.123.02.0010002000_0020002100
Explicación.
* Hemos 'estirado' la expresión con la ayuda de la opción /x para poder hacerla un poco más clara, y con comentarios.
* Dentro de ella, hemos convertido en paréntesis de NO captura aquellos que no nos interesan más tarde.
* La parte final de la expresión regular es esta: (?:|\.(\d+)_(\d+)), que quiere decir que hay dos opciones, separadas por '|'. En la primera opción, no hay nada, mientras que en la segunda, están las dos ristras de números a capturar. Todo está metido en un par de paréntesis de no captura ((?:...)) porque sólo nos interesa capturar los dos valores finales, no todo.
* En el bucle de filtrado, hacemos sort y grep en la misma línea.
* El filtrado es, aparte de la expresión regular y comprobar la existencia de $1 y $2, ver si esos valores son ciertos (son distintos de cero). Para ello, los convertimos de secuencias de dígitos a número, con sólo sumarles un 0. El resultado que nos interesa es que, justamente, sean distintos de cero.
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


Volver a Básico

¿Quién está conectado?

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