miércoles, 8 de diciembre de 2010

Como eliminar caracteres de texto por consola de comandos

Desde siempre cuando he tenido que modificar un archivo de texto, simplemente uso un editor como gedit, nano u algún otro y hago todo manualmente, sin embargo en ocasiones esa tarea puede ser muy tediosa o repetitiva para hacerlo uno mismo.

Por eso me puse a investigar un poco y logre encontrar un muy buen post que explica de forma simple como eliminar el carácter de nueva linea usando: tr, awk, perl, sed, c/c++ entre otros Yo voy a referirme únicamente a los comandos de consola.

Pueden encontrar el post original aquí.

Pues bien manos a la obra.
¿Cómo remover los saltos de línea en archivos o pipe streams en linux? A continuación enumeraré varios ejemplos sencillos usando comando del shell de GNU/Linux como tr, awk/gawk, perl, sed entre otros. Para este ejemplo supongamos que tenemos un archivo llamado dias.txt. Con el siguiente comando podemos ve el contenido de dicho archivo:
cat dias.txt
El resultado se muestra a continuación.
Lun
Mar
Mie
Jue
Vie
Sab
Dom

Si removiéramos los saltos de linea del archivo dias.txt se vería como sigue:
LunMarMieJueVieSabDom

Si en lugar de remover los saltos de linea los reemplazamos por espacios el contenido de dias.txt quedaría como sigue:
Lun Mar Mie Jue Vie Sab Dom

A continuación tenemos ejemplos de como reemplazar y eliminar el carácter de salto de línea para obtener los resultados mostras en los ejemplos antes mencionados.

usando tr (mi recomendación).Cualquiera de los siguiente comandos funciona para eliminar los saltos de línea del archivo dias.txt usando tr:
tr -d '\n'< dias.txt
cat dias.txt | tr -d '\n'
mientras que los dos ejemplos siguientes reemplazan el salto de línea por un espacio en blanco.
tr '\n' ' ' < dias.txt
cat dias.txt | tr '\n' ' ' 
usando awk (awk or gawk) Usando awk* para eliminar los saltos de línea, se puede usar alguno de los dos ejemplos siguientes:
awk '{ printf "%s", $0 }' dias.txt
cat dias.txt | awk '{ printf "%s", $0 }'
En tanto que para reemplazar por un espacio en blanco tenemos:
awk '{ printf "%s ", $0 }' dias.txt
cat dias.txt | awk '{ printf "%s ", $0 }' 
*Vale la pena resaltar que no se debe nunca una cadena no validada previamente al comando printf puesto que es una vulnerabilidad o riesgo de seguridad. Por lo tanto debemos usar { printf "%s ", $0 } y nunca usar { printf $0 }   usando perl En el caso de perl, tenemos las siguientes alternativas para eliminar los saltos de línea.
perl -e 'while (<>) { chomp; print; }; exit;' dias.txt
cat dias.txt | perl -e 'while (<>) { chomp; print; }; exit;' 
y las siguientes dos para reemplazar por un espacio en blanco.
perl -e 'while (<>) { chomp; print; print " "; }; exit;' dias.txt
cat dias.txt | perl -e 'while (<>) { chomp; print; print " "; }; exit;'
Aquí dejo algunos ejemplos adicionales en perl usando expresiones regulares, el cual es bastante más simple y limpio:
perl -p -e 's/\s+$/ /g' dias.txt
cat dias.txt | perl -p -e 's/\s+$/ /g' 
usando sed También se puede usar sed para eliminar los saltos de línea. La solución usando sed no es muy legible pero funciona.
sed ':a;N;$!ba;s/\n//g' dias.txt
cat dias.txt | sed ':a;N;$!ba;s/\n//g' 
sed '{:q;N;s/\n//g;t q}' dias.txt
Para reemplazar por un espacio en blanco podemos usar uno de los siguientes comandos.
sed ':a;N;$!ba;s/\n/ /g' dias.txt
cat dias.txt | sed ':a;N;$!ba;s/\n/ /g' 
sed '{:q;N;s/\n//g;t q}' dias.txt
La tercera alternativa fue sugerida por James the crypto.dsplabs.com.au en Linux Blog Forums. Otras alternativas posibles son:   xargs:
xargs echo < dias.txt
cat dias.txt | xargs echo
cat dias.txt | xargs echo -n
GNU Bash:
while read; do echo -n "$REPLY "; done < dias.txt
o esta otra más simple
echo -n `cat dias.txt`
Python
python -c 'import sys; print sys.stdin.read().replace("\n", " ")' < dias.txt
UPDATE 07-01-2011: Corregí algunos ejemplos que no se desplegaban correctamente el simbolo de menor que (<).