• Publicidad

Localizar caracteres hexadecimales 0D0A

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

Localizar caracteres hexadecimales 0D0A

Notapor pbellon » 2008-01-09 07:16 @344

Necesito hacer un script que correrá en plataforma Unix que lea un fichero y detecte si el retorno de carro es de Windows, es decir:

si el fichero a leer se ha generado en un Unix, el fin de línea en hexadecimal es '0A', pero si este fichero a leer se ha generado en un Windows y después se ha copiado al Unix el fin de línea en hexadecimal es '0D0A' y en este caso me genera otros errores en el tratamiento del fichero.

Necesito encontrar esta cadena, '0D0A' en hexadecimal.

Estoy usando la función chop, pero solo me devuelve en ambos casos el '0A', y esto no me es útil. Con la función substr ocurre lo mismo.
pbellon
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2004-10-22 06:48 @325

Publicidad

Notapor pbellon » 2008-01-09 07:18 @346

He cometido un pequeño error en la descripción que ahora corrijo, en Unix el fin de línea en hexadecimal es '0A'.
pbellon
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2004-10-22 06:48 @325

Notapor explorer » 2008-01-09 08:00 @375

Si lo que quieres saber es cuál es el penúltimo carácter de la línea, puedes usar substr y así saber si es tipo Windows.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -l

open FICHERO, "<kk.txt";
$linea = <FICHERO>;
close FICHERO;

#$fin_linea_2 = unpack "H*", substr($linea,-2,2);
#print $fin_linea_2;
#if ( $fin_linea_2 == chr(0x0D0A) ) {

if ( substr($linea, -2, 2) eq "\r\n" ) {
    print "Es Windows! Arg!";
    substr($linea, -2, 1) = ''; # Quitamos \r
}

chomp $linea;                   # Quitamos fin de línea

print $linea, " ", length $linea;

__END__
 
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
Última edición por explorer el 2008-01-09 08:26 @393, editado 1 vez en total
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 pbellon » 2008-01-09 08:19 @388

He probado esto y no me funciona. Por lo que veo este código debe ejecutarse en un Unix, el problema y creo que por esto no funciona, es que los chequeos debo hacerlos en un Windows.

La cosa es más o menos la siguiente:
Los ficheros (scripts) pueden generarse en un Windows (con notepad, ultraedit, etc.) o en un Unix (con vi, etc.). Estos ficheros pasan a un Windows a través de una herramienta que los gestiona (control de versiones, etc.) y los chequeos de ficheros se ejecutarán en el Windows. Si pasa los chequeos pasan a otro Unix, esto es a producción. Si originariamente los ficheros se crearon en un Unix no hay problema, pero si fue un Windows (aparece en este caso '0D0A') en ocasiones genera errores.
pbellon
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2004-10-22 06:48 @325

Notapor explorer » 2008-01-09 08:25 @392

Este es un ejemplo mejor: redefinimos lo que es un carácter fin de línea según lo que nos diga la primera línea del fichero:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

open FICHERO, "<kk.txt";
$linea = <FICHERO>;                 # Leemos la primera línea

if ( substr($linea, -2, 2) eq "\r\n" ) {
    print "Es Windows!\n";
    $/ = "\r\n";                    # Redefinimos lo que es fin de línea
}

seek FICHERO, 0, 0;                 # Volvemos al principio

while ( $linea = <FICHERO> ) {
    chomp $linea;                   # Quitamos fin de línea
    print $linea, "\n";
    # ...
}

close FICHERO;
 
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: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor explorer » 2008-01-09 08:34 @398

pbellon escribiste:Los ficheros (scripts) pueden generarse en un Windows (con notepad, ultraedit, etc.) o en un Unix (con vi, etc.). Estos ficheros pasan a un Windows a través de una herramienta que los gestiona (control de versiones, etc.) y los chequeos de ficheros se ejecutarán en el Windows. Si pasa los chequeos pasan a otro Unix, esto es a producción. Si originariamente los ficheros se crearon en un Unix no hay problema, pero si fue un Windows (aparece en este caso '0D0A') en ocasiones genera errores.


Bien, entonces la cuestión es que en alguna parte del proceso debemos asegurarnos que lo que tenemos está escrito en cristiano (es decir, en Unix).

Podría ser hacerlo en los Windows que generan los ficheros o en la máquina Unix de producción (casi mejor esta última).

Con la siguiente línea quitas todos los fines de línea de Windows que hubiera en el fichero, independientemente si se generó en Windows o no:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
perl -pe 's/\r\n/\n/' kk.txt > kk1.txt
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Puedes incluso hacer la edición en el mismo fichero:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
perl -p -i -e 's/\r\n/\n/' kk.txt
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Algunos Unix (es decir, Linux) ya traen el comando fromdos (y el todos) que realizan estas labores 'domésticas' de limpieza.

P.D. La mejor solución: no usar Windows.
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 pbellon » 2008-01-09 10:28 @478

Estoy probando tus consejos y substr($linea, -2, 2) no me devuelve "\r\n", me devuelve un carácter (cualquiera) y "\n".

Además la cosas es aún más compleja porque existen casos en los que los formatos DOS y Unix están mezclados, es decir originalmente se creó el fichero en Unix, pero se han introducido modificaciones vía Windows con lo cual te encuentras que unos saltos de línea son 0A y otros 0D0A. Además no puedo modificar el fichero original, solo puedo leerlo y decir si es válido o no. No me está permitido corregirlo. Por lo que tu última solución

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
perl -p -i -e 's/\r\n/\n/' kk.txt
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


aunque es muy buena no puedo aplicarla.

Sí, lo sé, las cosas son así.
pbellon
Perlero nuevo
Perlero nuevo
 
Mensajes: 36
Registrado: 2004-10-22 06:48 @325

Notapor explorer » 2008-01-09 11:32 @522

substr($linea,-2,2) devuelve los dos últimos caracteres. Si la línea es de tipo Unix, es claro que ese penúltimo carácter no será "0x0D".

Lo de que esté mezclado, es nuevo. En ese caso tenemos que ver línea a línea, pero solo para quitar el último carácter en el caso de que sea un "0x0D".

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

open FICHERO, "<kk.txt";

while ( $linea = <FICHERO> ) {

    chomp $linea;
    chop  $linea if substr($linea, -1) eq chr(0x0D);

    # Procesarlo o verificarlo
    print "$linea.\n";
}

close FICHERO;
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Esta es la solución formal, porque, realmente, no es necesaria. Con una simple línea ( s/\r\n/\n/ ) es más que suficiente para hacer todo el trabajo: solo va a cambiar las líneas tipo DOS.

Pero esto implica que hay que modificar los programas que están en producción, para que admitan esos ficheros mutantes.

Como no puedes modificar los ficheros que te llegan, aún se pueden hacer otras dos cosas: crear ficheros nuevos a partir de los originales o usar el 'pipe' del Unix. Por ejemplo, con el siguiente filtro

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
cat fichero.txt | perl -p -e 's/\r\n/\n/' | programa_principal
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


podemos encadenar el fichero original, filtrarlo y meter el resultado en el programa que nos interesa. Esto, naturalmente, es para los casos en que los programas admitan la entrada de los ficheros desde la entrada estándar.

Pero si no lo admiten, habrá que modificar o crear algún programa que haga ese filtrado:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
while ( <> ) {
    chomp;
    chop if substr($_, -1) eq chr(0x0D);
    print "$_\n";
}
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

O mejor esta otra (que hace lo mismo que la línea de comandos anterior):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
while (<>) {
    s/\r\n/\n/;
    print;
}
 
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: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor creating021 » 2008-01-09 17:30 @770

En algunos UNIX, existe algo llamado dos2unix... y en Perl también:
http://perlmonks.org/?node_id=7516

O sólo ejecutamos en la terminal si usar 2 procesos ni pipes:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
tr -d "\r" < dosfile.txt > unixfile.txt
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

( código tomado de PerlMonks.org )

Aunque con las respuestas de explorer ya está resuelto, solo escribo esto para mostrar que hay más de 100 soluciones... :D
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


Volver a Básico

¿Quién está conectado?

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

cron