• Publicidad

Problema CSV y expresiones regulares

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Problema CSV y expresiones regulares

Notapor AnKiSeTh » 2007-05-16 19:22 @848

Buenas!!

resulta que soy un novato en esto de Perl y tengo que hacer lo siguiente:

Se presenta un archivo CSV, este hay que convertirlo en una tabla HTML, el formato del archivo es el siguiente:

Código: Seleccionar todo
1,2,"Hola","5";
2,3;%12/12/1999%;


Las comillas representan a un string, los porcentajes, una fecha, esto deberia generar la siguiente tabla:

Código: Seleccionar todo
 <tr>
     <td>1</td>
     <td>2</td>
     <td><i>Hola</i></td>
     <td><i>5</i></td>
</tr>
<tr>
     <td>2</td>
     <td>3</td>
     <td><b>12/12/1999</b></td>
</tr>


El nombre del archivo se pasa como parametro al script y la salida es un archivo con el mismo nombre pero con extension .html.
Ahora bien, esto logre resolverlo con el siguiente código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

die "¿¿Y qué pasó con los parámetros??\n" unless $ARGV[0];
open(entrada,"<$ARGV[0]") or die "El archivo no existe\n";
$ARGV[0]=~s/\.csv/\.html/ or $ARGV[0].=".html";
open(salida,">$ARGV[0]");
print salida "<html>\n<head>\n</head>\n<body>\n<table border=\"1\">\n";
while(<entrada>){
        chomp;
        @w=split(/[;,]/);
        print salida "\t<tr>\n";
        foreach $e (@w){
                (($e=~s/%/<b>/) and ($e=~s/%/<\/b>/)) or (($e=~s/"/<i>/) and ($e=~s/"/<\/i>/));
                print salida "\t\t<td>$e</td>\n";
        }
        print salida "\t</tr>\n";
}
print salida "</table>\n</body>\n</html>\n";
close(entrada,salida);
 
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Eso resuelve el problema muy bien, el problema surge cuando me avisan que los strings PUEDEN contener , o ;
Al contener alguno de esos caracteres, el split los separa, y esa no es la idea, ya que el string "H,O,L,A", debiese aparecer en el .html como <td><i>H,O,L,A</i></td>
Pense en ponerle un unless en luego del split, con una condicion de calce, pero no lo he podido resolver

Alguien sabe como podria hacerlo??

De antemano, muchas gracias ^^
AnKiSeTh
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2007-05-16 19:10 @840
Ubicación: Entre la silla y el PC

Publicidad

Notapor creating021 » 2007-05-16 20:12 @883

Algunas cosas para tener en cuenta:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict; #Mira esto!
die "¿¿Y qué pasó con los parámetros??\n" unless @ARGV; #Hmmm....
open(entrada,"<$ARGV[0]") or die "Error: $ARGV[0] -> $!\n"; #puede que el archivo no sea rw, pero si que existas asi que...
$ARGV[0]=~s/\.csv/\.html/ or $ARGV[0].=".html";
open(salida,">$ARGV[0]") or die "Opps: $ARGV[0] -> $!\n"; #¿Podemos crearlo o no? Hay que ver eso
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El resto, puras regexp... @cosas = $linea =~ m@.... :? porque con split no puedes indicar como tomar los datos (si está segudido de comillas, comas et cetera)
Tengo que mejorar (yo) es ese aspecto (regexp) y por eso no te doy un ejemplo.
Expect the worst, is it the least you can do?
Avatar de Usuario
creating021
Perlero frecuente
Perlero frecuente
 
Mensajes: 595
Registrado: 2006-02-23 16:17 @720
Ubicación: Frente al monitor

Notapor explorer » 2007-05-16 20:14 @885

El tema del CSV puede ser muy, muy complicado. Tienes que saber si esa coma está dentro o no de un par de comillas. Es una búsqueda de delimitadores (comillas) balanceada (tiene que haber dos comillas en un campo entrecomillado). El contenido del campo puede ser cualquiera, aunque se supone que no debe haber otras comillas. Una pista podría ser que los campos entrecomillados empiezan por el conjunto ',"' y terminan por algo parecido: '",' (pero no siempre).

Otra estrategia sería hacer una búsqueda por los trozos de texto entrecomillado: /"([^"]*?)"/ y sustituirlo por otra cosa más simple, o quitarlo y guardarlo en otro sitio (un array), o...

Naturalmente, existen módulos que te resuelven muy fácil el problema, pero me parece que el profesor no te dejará usarlos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor AnKiSeTh » 2007-05-16 20:21 @889

Gracias!! no habia pensado en poner las condiciones a los open :P

Aun así no se me ocurre como resolver el problema que les comenté x_x

Aunque voy a seguir intentando =D
AnKiSeTh
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2007-05-16 19:10 @840
Ubicación: Entre la silla y el PC

Notapor AnKiSeTh » 2007-05-16 20:24 @892

explorer escribiste:El tema del CSV puede ser muy, muy complicado. Tienes que saber si esa coma está dentro o no de un par de comillas. Es una búsqueda de delimitadores (comillas) balanceada (tiene que haber dos comillas en un campo entrecomillado). El contenido del campo puede ser cualquiera, aunque se supone que no debe haber otras comillas. Una pista podría ser que los campos entrecomillados empiezan por el conjunto ',"' y terminan por algo parecido: '",' (pero no siempre).

Otra estrategia sería hacer una búsqueda por los trozos de texto entrecomillado: /"([^"]*?)"/ y sustituirlo por otra cosa más simple, o quitarlo y guardarlo en otro sitio (un array), o...

Naturalmente, existen módulos que te resuelven muy fácil el problema, pero me parece que el profesor no te dejará usarlos.


Ahi veré como lo resuelvo ^^
Sep, lei por ahi que hay módulos que ayudan mucho en esto, pero nos dijeron que NO DEBIAMOS usarlos. Solo lenguaje puro.
Bueno, no hay problema imposible, solo soluciones extrañas, a seguir pensando =D
AnKiSeTh
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2007-05-16 19:10 @840
Ubicación: Entre la silla y el PC

Notapor explorer » 2007-05-16 20:38 @901

Un truco sería conocer si existe un carácter que NO apareciese en ninguna parte de la entrada. Por ejemplo, el carácter '_'.

Si nos aseguran que ese carácter (o cualquier otro) no aparece en la entrada bajo ningún concepto, podemos hacer una sustitución de las comas entrecomilladas por ese carácter. Luego, hacer el split de forma normal, luego volver a dar a los elementos con '_' sus comas y luego hacer la transformación pedida.

Otra idea, más elaborada, es la de sustituir todo el texto entrecomillado por algo como '[[1]]', '[[2]]', etc. y los textos que se han quitado meterlos en un array (en los índices indicados por los dobles corchetes). Hacemos lo mismo de antes: split, reavivación de las comas quitadas antes y etc. etc.

El problema es si el profesor dice que puede salir ese carácter o esa combinación de corchetes.

Quizás... con una expresión regular... pero me suena algo complicada... yo creo que la tengo por algún sitio de este foro...
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor AnKiSeTh » 2007-05-16 20:49 @909

sep, io también había intentado con cambiar lo que este entre comillas, pero el ayudante me dijo que pueden ingresar CUALQUIER carácter...así que no pude seguir :P

Aparte, tengo otra duda, si tengo la frase :"Juanito","pedrito"
y quiero substituir lo que esta entre comillas, ¿me va a reemplazar Juanito y Pedrito o Juanito , Pedrito? porque "," está entre comillas también.
AnKiSeTh
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2007-05-16 19:10 @840
Ubicación: Entre la silla y el PC

Notapor explorer » 2007-05-17 17:02 @752

El siguiente código te dará una pista:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -lw
use strict;

while ( <DATA> ) {
    chomp;
    print;
    while ( m/"([^"]*)"/g ) {
        print $1;
    }
}

__DATA__
1,2,3,45,"Juanito","pedrito,juan",22
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor AnKiSeTh » 2007-05-17 22:08 @964

Gracias!! ^^
He estado estudiando y creo que ya estoy un poco mejor en esto de las regex. Pero me entra una duda:
He estado todo este tiempo trabajando con split...¿es mejor hacer un match y guardar las variables en un array o es está bien como voy?

Muchas gracias!!
AnKiSeTh
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2007-05-16 19:10 @840
Ubicación: Entre la silla y el PC

Notapor explorer » 2007-05-18 04:13 @217

Humm... yo creo que hay dos posibles ataques directos a este problema: o una máquina de estados e ir analizando carácter a carácter, o extraer y escapar primero los campos entrecomillados, para facilitar el trabajo del split.

Seguro que hay más soluciones, pero yo usaría la primera solución si tuviera menos conocimientos. Y de la segunda solución, se me ocurren ideas muy creativas para el caso de que el profesor insista en que no es posible escapar los entrecomillados por una secuencia conocida, pues podría darse. Aún en ese caso es posible resolverlo por el método de la extracción, sustitución, split, y final recuperación.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Siguiente

Volver a Básico

¿Quién está conectado?

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