Varias veces había intentado utilizar sed para eliminar el doble salto de línea que aparece en algunos ficheros, normalmente en las copias de la configuración de algunos switches. Nunca lo había conseguido y no entendía muy bien por qué. Creía que sed no entendía la especificación del caracter salto de línea como \n, claro que tampoco funcionaba \\n ni \\\n.

Cuando ví esta solución para sustituir saltos de línea por espacios entendí creí entender, como explicaré más adelante, que el problema es que sed va analizando línea por línea, eliminando el fin de línea de cada línea antes de realizar la búsqueda de patrones, por lo que, naturalmente, nunca encuentra dos saltos de línea seguidos en la misma línea.

La solución ofrecida para reemplazar saltos de línea por espacios y la traducción de su explicación son las siguientes:

sed :a;N;$!ba;s/\n/ /g

:a crea una etiqueta, lo que nos permite a continuación añadir una nueva línea al espacio de reconocimiento de patrones con N. $!ba indica que no se aplique esta regla en la última línea, para dejar el salto de línea al final del fichero.

Al modificarlo para reemplazar un doble salto de línea por uno probé lo siguiente con éxito:

sed :a;N;$!ba;s/\n\n/\n/g

Algo no cuadraba, pues según leí antes, sed eliminaba el salto de línea al final de cada línea, pero supuse que N, además de añadir una línea al espacio de búsqueda de patrones, evitaba la eliminación del salto de línea.

Queriendo jugar un poco y aportar mi granito de arena a la solución, pensé que en este caso no era necesario hacer una excepción con la última línea, debería funcionar igualmente aunque sed intentase aplicar sin éxito la sustitución en la última línea y probé así:

sed :a;N;s/\n\n/\n/g

Pero así no hace nada de nada. ¿Cómo? ¿perdona?, ¿la última parte no era únicamente para no aplicar la regla en la última línea? Pues no. Así que tuve que continuar leyendo en busca de una respuesta mejor que la aceptada y más votada, y así llegué a una respuesta, que hacía referencia a las FAQ de sed. Sin embargo, el fragmento incluido tampoco aclaraba mis dudas.

Así que seguí leyendo y casi al final del hilo, donde casi nunca hay buenas respuestas, encontré esta solución:

sed -i "s/\\\\\n//g" filename

De la que se obtenía para mi caso la siguiente, que funcionaba like a charm.

sed 's/\\\\\n\\\\\n/\\\\\n/g'

Quedaba claro que era mentira que sed eliminara los saltos de línea, así que no quedaba más remedio que seguir profundizando un poco, no para resolver el problema que ya estaba resuelto, sino porque no aguantaba más mi incultura en lo relacionado con sed.

Explorando un poco en las FAQ de sed encontré una serie de scripts de una línea, entre los que había dos que hacían algo parecido a lo que quería:

   # Delete all CONSECUTIVE blank lines from file except the first.
   # This method also deletes all blank lines from top and end of file.
   # (emulates "cat -s")
   sed '/./,/^$/!d' file       # this allows 0 blanks at top, 1 at EOF
   sed '/^$/N;/\n$/D' file     # this allows 1 blank at top, 0 at EOF

Otros scripts más que hacía lo mismo, pero no eran como los que había visto antes, pero ‘/./,/^$/.’, ¿esto que es?, no pararé hasta entender la sintaxis y semántica de todas estas soluciones, lo que finalmente, viendo algunos ejemplos más, logré.

'/./,/^$/!d'

La interpretación es la siguiente. /./,/^$/ especifica un rango sobre el que aplicar un comando, concretamente el rango entre ., es decir cualquier caracter, y ^$, es decir, una línea vacía. El ! a continuación niega la condición y la d elimina la coincidencia de la salida. Es decir, elimina los saltos de línea que no están precedidos por otro caracter.

Esto me llevó a esta sencilla y elegante solución con la que termino ya:

sed '/^$/d'

Es decir, borra las líneas vacías.

P.D. Reconozco que las diversas partes de este artículo son un poco incoherentes/inconexas/mejorables, pero tal como está ahora mismo sirve ya de ayuda para saber por donde tirar.

2 comentarios en “Eliminar doble salto de línea de un fichero

Deja una respuesta en Juanlú Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Puedes utilizar estas etiquetas y atributos HTML:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.