21
Sed en una-línea (sed one-liners) Dado que no hay muy buena documentación en español acerca del comando sed, me decidí a traducir una serie de excelentes artículos creados por Peteris Krumin. Le he pedido permiso expreso a su autor y no tuvo inconvenientes, así que aquí va. Nota del Traductor (NdT): No será una traducción total, dado que hay mucha información anecdótica y sólo me limitaré a la explicación del comando sed. Aquí comienza la traducción: Estos “one-liners” (sed en una-línea) fueron compilados por Eric Pement y los puedes descargar desde aquí. La mayoría de las personas están familiarizados con un comando de sed en particular: “ sde substituir. s/command/command/. Esto no es del todo satisfactorio. Sed tiene al menos 20 comandos diferentes. Incluso se puede escribir el tetris en él, tal y como hizo Julia Jomantaite. Los one-liners de Eric están divididos en varias secciones: Espaciado de un archivo Numeración Conversión y sustitución de texto Impresión selectiva de ciertas líneas Eliminación selectiva de ciertas líneas Aplicaciones especiales Antes de comenzar quisiera compartir la idea clave que cambió mi forma de pensar en sed. Fueron los cuatro espacios de sed: input stream, output stream, "pattern space" y hold buffer. Sed trabaja en el input stream (flujo de entrada) y produce un output stream (flujo de salida). Las líneas del flujo de entrada son colocadas en el "pattern space" (espacio de patrón) donde son modificadas. El hold buffer (buffer de almacenado) puede ser utilizado como un almacenamiento temporario. Ahora si, toma una copia de mi cheat sheet, imprímela y metámonos en los one-liners. Espaciado de un archivo 1 Espaciado doble en un archivo sed G Este sed de una sola línea utiliza el comando ‘G’. Si tomó la cheat sheet verá que el comando ‘G’ agrega en el "pattern space" una nueva línea seguida por el contenido del hold buffer. En este ejemplo, el buffer se encuentra vacío (sólo tres comandos ‘h’, ‘H’ y ‘x’ pueden modificar el buffer), por lo que se termina simplemente añadiendo una nueva línea en el "pattern space". Una vez que todos los comandos se han procesado (en este caso, sólo la ‘G’ comando), sed pone el contenido del "pattern space" en el output stream (flujo de salida) seguido de una nueva línea. Allí lo tenemos, dos saltos de línea – uno añadido por comando ‘G’ y otro por la salida. El archivo ha sido doble-espaciado. 2 Espaciado doble en un archivo que contiene líneas en blanco. Lo haremos de manera que la salida no contenga más de una linea en blanco entre dos líneas de texto.

Sed en Una Line [One Liners]

Embed Size (px)

Citation preview

Sed en una-línea (sed one-liners)

Dado que no hay muy buena documentación en español acerca del comando sed, medecidí a traducir una serie de excelentes artículos creados por Peteris Krumin. Le hepedido permiso expreso a su autor y no tuvo inconvenientes, así que aquí va.

Nota del Traductor (NdT): No será una traducción total, dado que hay mucha informaciónanecdótica y sólo me limitaré a la explicación del comando sed.

Aquí comienza la traducción:Estos “one-liners” (sed en una-línea) fueron compilados por Eric Pement y los puedesdescargar desde aquí.La mayoría de las personas están familiarizados con un comando de sed en particular: “s”de substituir. s/command/command/. Esto no es del todo satisfactorio. Sed tiene almenos 20 comandos diferentes. Incluso se puede escribir el tetris en él, tal y como hizoJulia Jomantaite.

Los one-liners de Eric están divididos en varias secciones:

✗ Espaciado de un archivo ✗ Numeración ✗ Conversión y sustitución de texto ✗ Impresión selectiva de ciertas líneas ✗ Eliminación selectiva de ciertas líneas ✗ Aplicaciones especiales

Antes de comenzar quisiera compartir la idea clave que cambió mi forma de pensar ensed. Fueron los cuatro espacios de sed: input stream, output stream, "pattern space" yhold buffer. Sed trabaja en el input stream (flujo de entrada) y produce un outputstream (flujo de salida). Las líneas del flujo de entrada son colocadas en el "patternspace" (espacio de patrón) donde son modificadas. El hold buffer (buffer de almacenado)puede ser utilizado como un almacenamiento temporario.

Ahora si, toma una copia de mi cheat sheet, imprímela y metámonos en los one-liners.

Espaciado de un archivo1 Espaciado doble en un archivosed GEste sed de una sola línea utiliza el comando ‘G’. Si tomó la cheat sheet verá que elcomando ‘G’ agrega en el "pattern space" una nueva línea seguida por el contenido delhold buffer. En este ejemplo, el buffer se encuentra vacío (sólo tres comandos ‘h’, ‘H’ y‘x’ pueden modificar el buffer), por lo que se termina simplemente añadiendo una nuevalínea en el "pattern space". Una vez que todos los comandos se han procesado (en estecaso, sólo la ‘G’ comando), sed pone el contenido del "pattern space" en el outputstream (flujo de salida) seguido de una nueva línea. Allí lo tenemos, dos saltos de línea –uno añadido por comando ‘G’ y otro por la salida. El archivo ha sido doble-espaciado.

2 Espaciado doble en un archivo que contiene líneas en blanco. Lo haremos de manera que la salida no contenga más de una linea en blanco entre doslíneas de texto.

sed '/^$/d;G'Esta línea sólo opera en las líneas que coinciden con una expresión regular /^$/. ¿Cuálesson esas líneas? Son líneas vacías. Tenga en cuenta que antes de hacer que la expresiónregular coincida, sed empuja el input stream al "pattern space". Al hacerlo, sed descartael último carácter (que es nueva línea). Las líneas en blanco contienen solo el carácter de nueva línea, de modo que después dehaber sido puestas en el "pattern space", este carácter se elimina y el "pattern space"permanece vacío. La expresión regular /^$/ coincide con el "pattern space" vacío y seaplica el comando ‘d’ que suprime el actual "pattern space", lee la siguiente línea, lopone en el "pattern space" y aborta el actual comando, y se inicia la ejecución desde elprincipio. Las líneas que no coinciden con el vacío obtendrán una nueva línea por elcomando ‘G’, al igual que en 1.1.En general, sed permite restringir las operaciones a algunas líneas (5, 27, etc), a una seriede líneas (líneas 10-20), a líneas que se correspondan a un patrón (por ejemplo las líneasque contengan la palabra “catonmat”), y en líneas entre dos patrones (por ejemplo entre“catonmat” y “coders”).

3. Triple-espaciado en un archivo.sed 'G;G'Los comandos se puede combinar en una misma línea, utilizando punto y coma ; . Estoscomandos serán ejecutados uno tras otro. Este one-liner realiza dos veces lo que elprimero (en 1.1), agrega dos nuevas líneas a la salida.

4. Deshacer espaciado doblesed 'n;d'Este one-liner asume que incluso las líneas en blanco estarán numeradas. Utiliza dosnuevos comandos ‘n’ y ‘d’. El comando ‘n’ imprime el "pattern space" actual (a menos queel parámetro -n haya sido especificado), vacía el "pattern space"actual y lee la siguientelínea entrada. Aquí vemos que ‘n’ imprime la primera, tercera, quinta, … línea y lee lasiguiente. La línea siguiente a la que se ha impreso es siempre una línea vacía. Ahora elcomando ‘d’ se ejecuta. Este comando borra el “pattern space” actual, lee la siguientelínea, pone la nueva línea en el "pattern space", aborta el comando actual y reinicia laejecución del primer comando pasado a sed. Ahora el comando ‘n’ vuelve a serejecutado, luego ‘d’, ‘n’, y así sucesivamente.Para hacerlo más corto: ‘n’ imprime la línea actual y ‘d’ vacía la línea, deshaciendo eldoble espaciado.

5. Insertar una línea en blanco sobre cada línea que coincida con “regex”.sed '/regex/{x;p;x;}'En este caso utiliza la operación de restricción junto a dos nuevos comandos ‘x’ y‘p’. Elcomando ‘x’ intercambia el hold buffer con el "pattern space". El comando‘p’ duplica laentrada, por lo que imprime el "pattern space" completo. Este one-liner funciona de lasiguiente manera: una línea es leída en el "pattern space", entonces el comando ‘x’intercambia con el hold buffer que está vacío. A continuación el comando ‘p’ imprime esevacío seguido de nueva línea, así que obtenemos una línea vacía impresa antes de la líneaactual. . Entonces ‘x’ intercambia nuevamente el hold buffer (que ahora contiene la línea)con el "pattern space". No hay más comandos así que sed imprime el "pattern space".Obtenemos entonces una nueva línea seguida de la línea que coincidía con regexo enotras palabras, una línea en blanco sobre cada línea procesada.También note los { … }. Esto es agrupamiento de comandos. Quiere decir: “ejecute todoslos comandos en {} sobre la línea que coincida con regex.

6. Insertar una línea en blanco debajo de cada línea que coincida con“regex”.sed '/regex/G'Este one-liner combina el comando ‘G’ descripto en #1 con que la línea coincida con/regex/, sed agrega una nueva línea al "pattern space". Las demás líneas que nocoincidan con /regex/ simplemente son mostradas sin ninguna modificación.

7. Insertar una línea en blanco encima y debajo de cada línea quecoincida con “regex”.sed '/regex/{x;p;x;G;}'En este caso se combinan los one-liners #5, #6 and #1. Las líneas que coincidan con/regex/ obtienen una nueva línea agregada antes y otra después.

Numeración.8. Numerar cada linea de un archivo (filename). Alineación a la izquierdadel número.sed = filename | sed 'N;s/\n/\t/'En este caso en realidad son dos one-liners separados. El primero usa un nuevo comandollamado ‘=’. Este comando opera directamente en el output stream e imprime el númerode línea actual. No hay manera de capturar el número de línea actual en el "patternspace". Por eso es que se llama al segundo one-liner. La salida del primero esredireccionada a la entrada del segundo. El segundo usa otro comando nuevo ‘N’. Elcomando ‘N’ agrega una nueva línea y la siguiente línea al "pattern space". Entonces elfamoso comando ‘s/\n/\t/’ es ejecutado el cual reemplaza el caracter recién agregado denueva línea con un tabulador. Luego de estas operaciones, las líneas son impresas.Para hacer más claro que hace ‘=’, veamos esto:line oneline twoline threeCorriendo el primer one-liner ‘sed = filename’, produce la salida:1line one2line two3line threeAhora el comando ‘N’ del segundo, junta estas líneas con un caracter de nueva línea:1\nline one2\nline two3\nline threeEntonces ‘s/\n/\t/’ reemplaza cada nueva línea con un tabulador, así que obtenemos:1 line one2 line two3 line threeEste ejemplo no es del todo exacto, ya que la unión de líneas con un caracter de nuevalínea ocurre línea tras línea, no en todas las líneas de una vez.

9. Numerar cada línea de un archivo (filename). Alineación a la derecha.sed = filename | sed 'N; s/^/ /; s/ *\(.\{6,\}\)\n/\1 /'Este one-liner es también una combinación. El primero numera las líneas igual que #8. Elsegundo usa ‘N’ para unir la línea que contiene el número con la actual. Luego usa dos

comandos substitutos para alinear a la derecha los números. Primero ‘s/^/ /‘ agrega 5espacios en blanco al inicio de la línea. Luego‘s/ *\(.\{6,\}\)\n/\1 /’ captura al menos seissímbolos antes de llegar al caracter de nueva línea y reemplaza esa captura más elcaracter de nueva línea con la referencia hacia atrás ‘/1′. Luego agrega dos espaciosfinales para separar el número del contenido de la línea.Es más sencillo ver un ejemplo que leer la explicación. Para claridad, se reemplaza‘\n’ por‘@’ y los espacios por ‘-’.$ echo "-----12@contents" | sed 's/-*\(.\{6,\}\)@/\1--/'----12--contentsLa expresión regular ‘-*\(.\{6,\}\)@’ indica a sed que un espacio ‘-’ seguido de al menos 6caracteres seguido de una nueva línea ‘@’. Sed los captura y los recuerda en \1. En elejemplo coinciden el primer espacio ‘-’ (la parte ‘-*’), entonces los siguientes seiscaracteres ‘—- 12′ y ‘@’. Ahora se reemplaza la parte coincidente de la cadena ‘—-12@’con el contenido capturado que es ‘—-12′ más dos espacios extra. El resultado final esque ‘—-12@’ se reemplaza con ‘—-12–’.

10. Numerar cada línea no vacía de un archivo (filename).sed '/./=' filename | sed '/./N; s/\n/ /'Nuevamente son dos one-liners. La salida del primero es enviada al segundo. El primerofiltra todas las líneas que tengan al menos un caracter. Cuando una línea vacía (con soloel caracter de nueva línea) es enviada al "pattern space", el caracter de nueva línea eseliminado. El segundo one-liner hace lo mismo que #8, excepto que solo las líneasnumeradas son unidas e impresas.

11. Contar el número de líneas en un archivo (emula “wc -l”).sed -n '$='En este caso se usa el switch “-n” para modificar el comportamiento de sed. Este switchle indica a sed que no envíe la línea a la salida luego de que haya sido procesada en el"pattern space". La única manera de hacer que sed muestre una salida cuando existe elswitch “-n” es usar un comando que modifique el output stream directamente (‘=’, ‘a’, ‘c’,‘i’, ‘I’, ‘p’, ‘P’, ‘r’ y ‘w’).En este one-liner el comando ‘$’ es en realidad una restricción alaparecer junto a ‘=’. El comando ‘=’muestra el número de línea actual, pero al seraplicado a ‘$’ que es la última línea, sólo se imprime el número de la última línea delarchivo.

Conversión y Sustitución de Texto12. Convertir caracteres de nueva línea de DOS/Windows (CRLF) a Unix(LF).sed 's/.$//'Este asume que todas las líneas terminan con CR+LF (carriage return + line feed oretorno de carro + nueva línea) y que estamos en un ambiente Unix. Una vez que la líneaes ingresada al "pattern space", la nueva línea es descartada, así que nos quedan líneasterminadas en CR. El comando ‘s/.$//’ borra el último caracter que coincida con el últimocaracter de la línea (regex ‘.$’) y lo substituye con nada. Ahora cuando el "pattern space"muestra su salida, es agregada la nueva línea y nos queda un caracter LF.

13. Otro modo de convertir DOS/Windows CRLF a Unix LF.sed 's/^M$//'Este one-liner nuevamente asume que estamos en un ambiente Unix. Elimina el caracterde control de retorno de carro ^M. Usualmente puedes ingresar un caracter de control^M literalmente pulsando Ctrl-V y luego Ctrl-M.

14. Otra forma más de convertir DOS/Windows CRLF a Unix LF.sed 's/\x0D$//'Este one-liner asume que estamos en un ambiente Unix y además que usa una versión desed que soporta códigos de escape hexadecimales, tales como GNU sed. El valorhexadecimal para CR es 0×0D (13 decimal). En este caso se elimina ese caracter.

15-17. Convertir Unix LF a DOS/Windows CRLF.sed "s/$/`echo -e \\r`/"Este one-liner también asume que estamos en un ambiente Unix. Utiliza la llamada deshell ‘echo -e \\r’ para insertar un retorno de carro en la expresión de sed. El comando “s/$/char/” agrega este caracter obtenido al final del "pattern space".

18. Otra forma de convertir Unix LF a DOS/Windows CRLF.sed 's/$/\r/'Este one-liner asume que utilizamos GNU sed. Esta versión es más inteligente que otrasversiones ya que puede utilizar códigos de escape en la parte de reemplazo.

19. Convertir Unix LF a DOS/Windows CRLF desde DOS/Windows.sed "s/$//"Este one-liner trabaja desde DOS/Windows. Reemplaza nada con nada y envía la línea aloutput stream donde se agrega el caracter CRLF.

20. Otra forma de convertir Unix LF a DOS/Windows CRLF desdeDOS/Windows.sed -n pEste similar a #19. También la forma más corta de hacer lo mismo es:sed ''

21. Convertir DOS/Windows LF a formato Unix CRLF desdeDOS/Windows.sed "s/\r//"Eric dice que este one-liner trabaja solo con UnxUtils v4.0.7 o superior. En este caso elcaracter de retorno de carro es quitado de las líneas. Luego, cuando son impresas elCRLF es agregado automáticamente.Eric también menciona que la única manera de convertir LF a CRLF en DOS es usar tr:tr -d \r <infile >outfile

22. Borrar espacios iniciales (tabs y espacios) de cada línea.sed 's/^[ \t]*//'Muy simple, busca al inicio de cada línea una coincidencia de cero o más espacios ytabuladores y los reemplaza con nada, los borra.

23. Borrar espacios finales (tabs y espacios) de cada línea.sed 's/[ \t]*$//'Este es muy similar a #22. Realiza la misma sustitución simplemente buscando cero omás espacios y tabuladores al final de cada línea y reemplazándolos con nada,borrándolos.

24. Borrar espacios iniciales y finales de cada línea.sed 's/^[ \t]*//;s/[ \t]*$//'En este caso combina #22 y #23. Primero elimina los espacios iniciales, luego elimina losfinales.

25. Insertar cinco espacios al principio de cada línea.sed 's/^/ /'Busca el inicio de la línea (^) que es un caracter de null-string y lo reemplaza por cincoespacios.

26. Alinear a la derecha en un ancho de 79 columnas.sed -e :a -e 's/^.\{1,78\}$/ &/;ta'Este one-liner utiliza una nueva opción de línea de comando y dos nuevos comandos. Laopción de línea de comando es ‘-e’, que permite escribir los comandos por separados. Enlugar de utilizar ; se utiliza la opción -e para clarificar y hacerlo más legible. En este caso,el primer -e crea una etiqueta llamada “a” usando el comando “:”. El segundo “-e” utilizaun nuevo comando‘t’. Este comando se dirige a una etiqueta si el último comando hamodificado el"pattern space". Esta técnica de bifurcación puede ser usada para crearbucles dentro de sed. En este one-liner, el comando pasa la cadena y la alinea a laderecha hasta que el total de la cadena excede 78 caracteres. El símbolo ‘&’ en elcomando de sustitución indica la cadena que ha coincidido.Traducido a lenguaje moderno, se vería como esto:while (str.length() <= 78) { str = " " + str}

27. Centrar todo el texto en la mitad de 79 columnas.sed -e :a -e 's/^.\{1,77\}$/ & /;ta'Este es muy similar al #26, sólo que en lugar de rellenar a la izquierda de la línea lo varealizando a ambos lados hasta que alcanza al menos 77 caracteres. Entonces otros dosespacios son agregados en la última iteración y crece hasta 79 caracteres.Otro modo de hacer lo mismo sería:sed -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/'Este ejemplo va añadiendo espacios al comienzo de la cadena hasta que ésta llega a 78caracteres. Entonces el comando adicional ‘s/\( *\)\1/\1/’ divide los espacios en blancoinciales a la mitad.

28. Sustituir (buscar y reemplazar) la primera ocurrencia de “foo” con“bar” en cada línea.sed 's/foo/bar/'Este la manera más simple posible. Utiliza el comando sustituir y lo aplica en cada línea,así se reemplaza “foo” con “bar”.

29. Sustituir (buscar y reemplazar) la cuarta ocurrencia de “foo” con“bar” en cada línea.sed 's/foo/bar/4'Este one-liner utiliza una bandera para el comando de sustitución. Sin esta bandera laprimera ocurrencia sería cambiada. Con una bandera numérica como “/1 , “/2 , etc. y sólo″ ″esa ocurrencia será cambiada. En este caso hay un “/4 con lo cual la cuarta aparición será″reemplazada.

30. Sustituir (buscar y reemplazar) todas las ocurrencias de “foo” con“bar” en cada línea.sed 's/foo/bar/g'Este one-liner utiliza otra bandera, en este caso la “/g” que indica global. Con unabandera global las sustituciones son para todas las ocurrencias.

31. Sustituir (buscar y reemplazar) la primera ocurrencia de unaocurrencia repetida de “foo” con “bar” en cada línea.sed 's/\(.*\)foo\(.*foo\)/\1bar\2/'Intentemos entender con este ejemplo$ echo “this is foo and another foo quux” | sed ‘s/\(.*\)foo\(.*foo\)/\1bar\2/’this is bar and another foo quuxComo puedes ver, en la línea hay dos apariciones de foo, pero solo la primera esreemplazada.

32. Sustituir (buscar y reemplazar) la última ocurrencia de “foo” con“bar” en cada línea.sed 's/\(.*\)foo/\1bar/'En este caso se utiliza un grupo de captura el cual guarda todo hasta “foo”. Reemplaza lalínea con lo capturado y agrega “bar”.

33. Sustituir (buscar y reemplazar) todas las ocurrencias de “foo” con“bar” en todas las líneas que contengan “baz”.sed '/baz/s/foo/bar/g'En este one-liner se usa una expresión regular para restringir la sustitución a las líneasque contengan “baz”. El resto de las líneas (donde no coincida) simplemente seránimpresas.

34. Sustituir todas las ocurrencias de “foo” con “bar” en todas las líneasque NO contengan “baz”sed '/baz/!s/foo/bar/g'Los comandos de sed pueden ser negados utilizando “!”.

35. Cambiar los textos “scarlet”, “ruby” o “puce” a “red”.sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g'En este caso se usan tres sustituciones consecutivas. La primera reemplaza “scarlet” con“red”, la segunda reemplaza “ruby” con “red” y la última reemplaza “puce” con “red”.Si estás usando GNU sed, se puede realizar más sencillamente:gsed 's/scarlet\|ruby\|puce/red/g'GNU sed provee expresiones regulares más avanzadas. Note que utiliza “\|” como un o(or) lógico.

36. Invertir el orden de las líneas (emular el comando tac).sed '1!G;h;$!d'Este one-liner actúa como la utilidad tac. Es más sencillo explicarlo mediante un ejemplo:Supongamos que tenemos un archivo con 3 líneas:$ cat filefoobarbaz

Ejecutando sed, se invierte el orden de las líneas:$ sed '1!G;h;$!d' filebazbarfooLa primera parte “1!G” es aplicada a todas las líneas excepto la primera. El segundocomando “h” se aplica a todas las líneas y el tercer comando “$!d” se aplica a todas laslíneas excepto la última.Veamos la ejecución:Línea 1: Sólo “h” se aplica a la primera línea. Ésta se copia al hold buffer. El hold bufferahora contiene “foo”. Al aplicarse el comando “d” la salida es vacía.Línea 2: El comando “G” es aplicado. Agrega el contenido del hold buffer al"patternspace". El "pattern space" contiene ahora “bar\nfoo”. El comando “h” copia entonces“bar\nfoo” al hold buffer, finalmente no hay salida.Línea 3: El comando “G” es aplicado y agrega el contenido del hold buffer a la tercera yúltima línea. El "pattern space" contiene “baz\nbar\nfoo”. Como es la última línea, “$!d”no se aplica y el "pattern space" es impreso. Se imprimen las líneas del archivo en ordeninverso.Aquí hay otra forma de realizar lo mismo:sed -n '1!G;h;$p'Se silencia la salida con el switch “-n” y se fuerza a escribir la salida con el comando “p” enla última línea.Estos dos one-liners utilizan mucha memoria dado que mantienen el archivo completo enel hold buffer en orden inverso hasta el momento de su impresión. Comorecomendación, trate de no utilizar estos one-liners cuando tenga que procesar archivosgrandes.

37. Invertir una línea (emular el comando “rev”).sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'Este es bastante complicado. Vamos a re-formatearlo para ver mejor:sed '/\n/ !Gs/\(.\)\(.*\n\)/&\2\1///Ds/.//'La primer línea “/\n/ !G” agrega una nueva línea al final del "pattern space" si no hubieraninguno.La segunda línea “s/\(.\)\(.*\n\)/&\2\1/” es un simple s/// que agrupa el primer caractercomo \1 y el resto como \2. Entonces se reemplaza toda la cadena con “&\2\1″, donde“&” es todo el texto (“\1\2 ). Por ejemplo, si la cadena de entrada es “1234 luego de″ ″aplicar la expresión s///, se convertiría en”1234\n234\n1 .″La tercera línea es “//D”. Este es clave en este one-liner. Un patrón vacío // coincide conla última regex, sería lo mismo que: /\(.\)\(.*\n\)/D. El comando“D” elimina desde elcomienzo hasta el caracter de nueva línea, entonces continúa la edición con el primercomando en el script. Crea un bucle. Mientras que /\(.\)\(.*\n\)/ sea cumplido, sedretomará todas las operaciones previas. Luego de varios ciclos, el texto en el "patternspace" se convierte en “\n43212 . Entonces ″ /\(.\)\(.*\n\)/ falla y sed continúa con elsiguiente comando.La cuarta linea “s/.//” elimina el primer caracter en el "pattern space" que es un caracterde nueva línea (\n). El contenido en el "pattern space" se convierte en “4321 el inverso″de “1234 .″

Ahí lo tienes, la línea ha sido invertida.

38. Unir un par de líneas (emular el comando “paste”).sed '$!N;s/\n/ /'En este caso se unirán dos líneas consecutivas con el comando “N”. Quedan unidas conun “\n” entre ellas. El comando sustituye este caracter con un espacio uniendo ambaslíneas en una sola.

39. Agregar una línea a la próxima si ésta termina en backslash “\”.sed -e :a -e '/\$/N; s/\\n//; ta'La primera expresión crea una etiqueta ‘:a’. La segunda expresión verifica que la líneaactual termine en backslash “\”. Si se cumple, une la línea con la siguiente utilizando elcomando “N”, con lo cual los caracteres \ y \n son eliminados por“s/\\n//”. Con “t” sevuelve a iniciar el ciclo buscando otra línea que termine en \.Aquí hay un ejemplo:$ cat filenameline one \line twoline three$ sed -e :a -e '/\$/N; s/\\n//; ta' filenameline one line twoline threeLas líneas uno y dos son unidas ya que la primera termina en backslash.

40. Agregar una línea a la anterior si ésta comienza con un signo “=”.sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'Este one-liner también comienza creando una etiqueta. Entonces verifica que no sea laúltima línea y agrega la siguiente línea a la actual con el comando “N”. Si la líneacomenzara con “=”, sed abre otros procesos para ver que haya más líneas que comiencencon “=”. Durante este proceso, una sustitución se ejecuta eliminado la nueva línea y el =.Si la sustitución falla, se imprime el "pattern space", se vacía y se repite el procesoUn ejemplo:$ cat filenameline one=line two=line threeline four$ sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D' filenameline one line two line threeline four

41. Grupo de dígitos en una cadena numérica (poner comas de miles)sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'Este one-liner convierte una cadena numérica como “1234567 a “1,234,567 .″ ″Primero se crea una etiqueta. Luego captura dos grupos de dígitos. El primer grupo sontodos los dígitos hasta los últimos tres. Los últimos tres dígitos son capturados en elsegundo grupo. Entonces los dos grupos son separados por una coma. Luego las mismasreglas son aplicadas una y otra vez a la línea hasta que todos los números hayan sidoagrupados de a tres.El comando de sustitución “\1,\2 separa los grupos con una coma.″Un ejemplo rápido sería: una cadena como 12345678 se separaría en 12345,678. En lasegunda aplicación de las reglas quedaría 12,345,678. Si se intenta aplicar las reglas

nuevamente, dará error con lo cual se imprime y sed comienza a trabajar sobre la líneasiguiente.Si se utiliza GNU sed es más sencillo:gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta'

42. Agregar comas a número con punto decimal y signos +/-.gsed -r ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'Este trabaja únicamente en GNU sed. Trabaja sobre expresiones regulares extendidasusando el switch ‘-r’. Entonces hace un bucle sobre las líneas con tres grupos y separa losdos primeros del tercero con una comaEl primer grupo se asegura que ignoramos los caracteres no numéricos + o -. Si no haycaracteres iniciales, entonces comienza normalmente.Una vez que los grupos han sido capturados como “\1\2,\3 la sustitución se realiza y se″vuelve a comenzar hasta que toda la cadena haya sido procesada.

43. Agregar una línea en blanco luego de cada cinco líneassed 'n;n;n;n;G;'El comando “n” es llamado cuatro veces. Cada vez que es llamado imprime el "patternspace" actual, lo vacía y lee la siguiente línea. Luego de ejecutarse cuatro veces y laquinta línea está dentro del "pattern space", el comando “G” es llamado agregando unanueva línea a esta última. Entonces la siguiente ronda de “n” es procesada, luego “G” yasí sucesivamente.En GNU sed se puede realizar así:gsed '0~5G'

Impresión selectiva de ciertas líneas44. Imprimir las 10 primeras líneas de un archivo (emular “head -10 )″sed 10qEste one-liner restringe el comando ‘q’ a la línea 10. Esto significa que el comando esejecutado solo cuando sed lee la décima línea. Para el resto de las líneas no hay comandoespecificado por lo que la acción predeterminada es imprimir la línea tal y cómo está.Este one-liner imprime las líneas 1 a 9 sin modificar y en la décima termina. ¿Notas algoextraño? Se supone que imprimiríamos las 10 primeras líneas de un archivo, pero pareceque sólo se imprimen las primeras 9… No te preocupes. El comando ‘q’ es astuto pornaturaleza. Al salir usando ‘q’, sed imprime el contenido del “"pattern space"” y sólodespués de eso termina. Como resultado se imprimen las líneas del 1 al 10.Por favor ve la primera parte de este artículo para una explicación de “"pattern space"”.

45. Imprimir la primera línea de un archivo (emular “head -1 ).″sed qLa explicación es prácticamente la misma que para el ejemplo anterior. Sed termina eimprime el contenido del "pattern space" (que es justamente la primera línea).

46. Imprimir las últimas 10 líneas de un archivo (emular “tail -10 ).″sed -e :a -e '$q;N;11,$D;ba'Este sed es complejo de explicar. Siempre mantiene las últimas 10 líneas en el"patternspace" y en la última línea sed termina y las imprime.La primer comando ‘-e :a’ crea una etiqueta llamada ‘a’. El segundo ‘-e’ hace lo siguiente‘$q’ : si es la última línea, sale y se imprime el "pattern space", si no, ejecuta trescomandos ‘N’, ’11,$D’ y ‘ba’. El comando ‘N’ lee la línea siguiente de la entrada y la agregaal "pattern space". La línea es separada del resto del"pattern space" por un caracter de

nueva línea. El comando ’11,$D’ ejecuta el comando ‘D’ si el número de la línea actual esnayor o igual a 11 (’11,$’ indica desde la línea 11 hasta el final del archivo). El comando ‘D’elimina la porción del"pattern space" hasta el primer caracter de nueva línea. El últimocomando ‘ba’vuelve a la etiqueta llamada ‘a’ (creada al principio). Esto garantiza queel"pattern space" nunca contiene más de 10 líneas, porque cuando la línea 11 esagregada, la línea 1 es eliminada, cuando la 12 se agrega, se borra la 2, etc.

47. Imprime las últimas 2 líneas de un archivo (emular “tail -2 ).″sed '$!N;$!D'Este también es complejo. Primero la dirección ‘$!’ restringe los comandos ‘N’ y‘D’ atodas las líneas excepto la última.Note como la dirección está negada. Si ‘$<comando>’ restringe el comando a la últimalínea, entonces ‘$!<comando>’ restringe el comando a todas las líneas excepto la última.Esto puede ser aplicado a todas las operaciones de restricción.En este one-liner, el comando ‘N’ lee la línea siguiente desde la entrada y la agrega al"pattern space". El comando ‘D’ elimina todo en el "pattern space"hasta el primersímbolo ‘\n’ (nueva línea). Estos dos comandos siempre mantienen solo las líneas leídasmas recientes dentro del "pattern space". Cuando se procesa la anteúltima línea, ‘N’ esejecutado y agrega la última línea al"pattern space". ‘D’ no se ejecuta dado que ‘N’ haconsumido la última línea. En este momento sed termina e imprime las últimas dos líneasdel archivo que estaban contenidas en el "pattern space".

48. Imprimir la última línea de un archivo (emular “tail -1 ).″sed '$!d'Este one-liner descarta todas las líneas excepto la última. El comando ‘d’ elimina el"pattern space" actual, lee la siguiente línea y reinicia la ejecución de los comandosdesde le principio. En este caso es un loop que irá borrando una a una las líneas hastaque llegue a la última. Debido a la restricción ‘$!’ no se elimina la última y así el "patternspace" es mostrado.Otra manera de realizar lo mismo:sed -n '$p'El parámetro ‘-n’ suprime automáticamente la impresión del "pattern space". Al colocarel comando explícito ‘p’ junto al final de archivo ‘$’ se obtiene el mismo resultadoanterior.

49. Imprimir la anteúltima línea de un archivo.Eric nos da 3 one-liners diferentes para hacer esta tarea. El primero imprime una línea enblanco si el archivo contiene tan sólo una línea:sed -e '$!{h;d;}' -e xEn este caso se ejecutan los comandos ‘h;d’ para todas las líneas excepto la última: ‘$!{h;d}’. El comando ‘h’ coloca la línea actual en el hold buffer y luego‘d’ borra la líneaactual. Luego se vuelven a ejecutar los comandos h;d. Por cada línea, ésta se copia al holdbuffer. En la última línea ‘h;d’ no se ejecuta. En este momento ‘x’ es ejecutado y seproduce un intercambio del contenido del hold buffer con el "pattern space". Sirecuerdas, la anteúltima línea fue previamente almacenada en el hold buffer, ‘x’ hace elintercambio y sed termina imprimiéndola.En el caso de un archivo con una sola línea, sólo el comando ‘x’ es ejecutado con lo cual elhold buffer que está vacío se intercambia con el "pattern space" y se imprime una líneaen blanco.El segundo one-liner imprime la primera línea si el archivo contiene sólo 1 línea:sed -e '1{$q;}' -e '$!{h;d;}' -e xÉste está dividido en dos partes. La primera parte ’1{$q;}’ maneja el caso en el que el

archivo contenga sólo una sola línea. La segunda parte ‘$!{h;d;} x’ es exactamente lomismo que el one-liner anterior.La primera parte dice que si es la primera línea ’1 entonces se ejecutará ′ ‘$q’, estecomando dice que si es la última línea, entonces termina. Lo cual es correcto si el archivocontiene una sola línea.El tercer one-liner imprime un vacío en archivos de una sola línea:sed -e '1{$d;}' -e '$!{h;d;}' -e xEste también está dividido en dos partes. La primera es ’1{$d;}’ y la segunda esexactamente lo mismo a los dos anteriores one-liners. La primera parte dice que si es laprimera línea entonces se ejecuta ‘$d’, este comando dice que si es la última líneaentonces se elimina el "pattern space" y se comienza otra vez. Como el archivo contieneuna sola línea, no hay nada por hacer y sed termina imprimiendo una línea vacía.

50. Imprimir solo las líneas que igualan a la expresión regular (emular“grep”).sed -n '/regexp/p'Este one-liner utiliza el switch ‘-n’ para evitar mostrar las líneas y hace uso del comando‘p’ para imprimir sólo aquellas líneas que concuerdan con ‘/regexp/’. Aquellas líneas queno concuerden serán descartadas y las que si serán impresas.Otro one-liner que realiza lo mismo es:sed '/regexp/!d'En este caso se eliminan todas las líneas que no concuerdan con ‘/regexp/’. El ‘!’antes delcomando ‘d’ invierte la selección.

51. Imprime sólo las líneas que no concuerdan con la expresión regular(emular “grep -v”).sed -n '/regexp/!p'Este one-liner es el inverso del previo.Este one-liner utiliza el switch ‘-n’ para evitar mostrar las líneas y hace uso de ‘!p’paraevitar imprimir aquellas líneas que si concuerden con ‘/regexp/’. Otro ejemplo para esto:sed '/regexp/d'En este caso se ejecuta el comando ‘d’ en todas las líneas en que igualen a‘/regexp/’.

52. Imprimir la línea anterior a regexp, pero no la que la iguala.sed -n '/regexp/{g;1!p;};h'Este one-liner guarda cada línea en el hold buffer con el comando ‘h’. Si una líneaconcuerda con regexp, el hold buffer (que contenía la línea anterior) es copiado con elcomando ‘g’ al "pattern space" y éste es impreso a través de ‘p’. El’1!’ restringe a ‘p’ paraque no imprima la primera línea ya que no hay líneas anteriores.

53. Imprimir la línea siguiente a regexp, pero no la que la iguala.sed -n '/regexp/{n;p;}'Primero que nada se deshabilita la impresión con el switch ‘-n’. Luego para todas laslíneas que concuerdan con ‘/regexp/’, se ejecutan los comandos ‘n’ y ‘p’. El comando ‘n’ esel único que depende de la bandera ‘-n’. Si ‘-n’ es especificado vaciará el "pattern space"actual y leerá la línea siguiente de la entrada. Si ‘-n’ no es especificado, imprimirá el"pattern space" actual antes de vaciarlo. En este caso se ‘n’ vacía el "pattern space", leela siguiente línea y luego ‘p’ imprime esa línea.

54. Imprimir una línea anterior y posterior a regexp. También imprimir lalínea que concuerda con regexp y su número de línea (emular “grep -A1-B1 ).″sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e hPrimero veamos el comando ‘h’ al final del script. Se ejecuta en cada línea y guarda lalínea del "pattern space" al hold buffer. La idea de guardar cada línea en el hold buffer esque si la siguiente línea concuerda con ‘/regexp/’entonces la línea previa estarádisponible en el hold buffer.Ahora veamos lo complicado ‘/regexp/{=;x;1!p;g;$!N;p;D;}’. Se ejecuta sólo si las líneasconcuerdan con ‘/regexp/’. La primera cosa que hace es imprimir el número de líneaactual con el comando ‘=’. Luego intercambia el hold buffercon el "pattern space" con elcomando ‘x’. Tal como se explicó, ‘h’ se asegura que el hold buffer siempre contenga lalínea anterior. Luego, si no es la primer línea (comprobamos con ’1!p’) imprimimos el"pattern space" que es efectivamente la línea anterior. Ahora el comando ‘g’ esejecutado, copia la línea original que fue recién intercambiada con el hold buffer desdeel "pattern space". ‘$!N’ consulta que no sea la última linea. ‘N’ agrega la siguiente líneaal "pattern space" y las separa con un ‘\n’. El "pattern space" ahora contiene la línea queconcuerda con‘/regexp/’ y la línea siguiente. El comando ‘p’ las imprime. Con ‘D’borramos la línea actual (la que ha igualado a ‘/regexp/’) del "pattern space" yfinalmente‘h’ es ejecutado nuevamente, lo que coloca el contenido del "pattern space"en elhold buffer. Como ‘D’ borró la línea actual, la siguiente línea fue puesta en elholdbuffer.

55. Grep para “AAA” y “BBB” y “CCC” en cualquier orden.sed '/AAA/!d; /BBB/!d; /CCC/!d'Este one-liner invierte el comando ‘d’ al ser ejecutado en líneas que no contienen ‘AAA’,‘BBB’ y ‘CCC’. Si una línea no contiene alguno de estos items será eliminada y sedcontinúa con la línea siguiente. Sólo si los tres patrones están presentes, entonces sedimprimirá la línea.

56. Grep para “AAA” y “BBB” y “CCC” en ese orden.sed '/AAA.*BBB.*CCC/!d'Este one-liner elimina las líneas que no coincidan con la expresiónregular‘/AAA.*BBB.*CCC/’. Por ejemplo una línea ‘AAAfooBBBbarCCC’ será impresa pero‘AAAfooCCCbarBBB’ no.También se puede escribir como:sed -n '/AAA.*BBB.*CCC/p'

57. Grep para “AAA” o “BBB”, o “CCC”.sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e dEste one-liner usa el comando ‘b’ para ir al final del script si la línea coincide con ‘AAA’ o‘BBB’ o ‘CCC’. Al final del script la línea simplemente es impresa. Si la línea no coincidecon algún patrón el script alcanza el comando ‘d’ que borra dicha línea.También se puede utilizar gsedgsed '/AAA\|BBB\|CCC/!d'gsed -r '/AAA|BBB|CCC/!d'o tambiéngsed -rn '/AAA|BBB|CCC/p'

58. Imprimir un párrafo que contenga ‘AAA’ (párrafos están separadospor líneas en blanco).sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'Primero notemos que este one-liner está dividido en dos partes. La primera parte es ‘/./{H;$!d;}’ y la segunda es ‘x;/AAA/!d’.En la primera parte encontramos el interesante patrón ‘/./’. ¿Qué crees que hace? Bien,una línea que separa párrafos sería una línea en blanco, es decir que no hay caracteres enella. Este patrón iguala solo a las líneas que no separan párrafos. Con el comando ‘H’ lasvamos agregando al hold buffer. Además prevenimos que sean mostradas con elcomando ‘d’ (excepto porque ‘$!’ restringe a ‘d’ salvo para la última línea). Una vez quesed ve una línea en blanco, el patrón ‘/./’ ya no coincide y la segunda parte del one-lineres ejecutada.La segunda parte intercambia el hold buffer con el "pattern space" usando el comando‘x’. El "pattern space" ahora contiene un párrafo completo. A continuación sed testea siel párrafo contiene ‘AAA’. Si lo contiene sed no hace nada lo que resulta en la impresióndel párrafo. Si no contiene ‘AAA’, sed ejecuta el comando ‘d’ el cuál borra el "patternspace" sin mostrarlo y recomienza.

59. Imprimir un párrafo si contiene ‘AAA’ y ‘BBB’ y ‘CCC’ en cualquierorden.sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'Este one-liner está dividido también para mejor claridad. La primera parte esexactamente igual al one-liner anterior. La segunda parte es muy similar al #55.El comando ‘x’ en la segunda parte intercambia el hold buffer que contiene el párrafocon el "pattern space". A continuación se testean tres cosas: que el párrafo contenga‘AAA’, ‘BBB’ y ‘CCC’. Si el párrafo no contiene alguno de ellos, el comando ‘d’ es ejecutadoborrando el "pattern space"; si coinciden todos sed mostrará el párrafo y recomenzará.

60. Imprimir un párrafo si contiene ‘AAA’ o ‘BBB’ o ‘CCC’.sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e dLa primera parte es exactamente como los dos anteriores y no requiere explicación. Lasegunda parte es casi como #57.El comando ‘x’ intercambia el párrafo almacenado en el hold buffer con el"patternspace". Entonces se realiza el siguiente test: si el "pattern space" contiene ‘AAA’ sedcontinúa hasta el fin del script ejecutando el comando ‘b’ que mostraría el párrafocontenido. Si ‘AAA’ no coincide se testea la existencia de ‘BBB’, y lo mismo para ‘CCC’. Sininguno de estos patrones coincide, sed ejecuta el comando ‘d’ eliminando todo yrecomenzando desde el principio.Aquí hay otra manera de realizar lo mismo con GNUsed:gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d'

61. Imprimir sólo las líneas que tengan 65 o más caracteres de longitud.sed -n '/^.\{65\}/p'Este one-liner imprime las líneas que tienen m65 o más caracteres de longitud. Se realizausando la expresión regular ‘^.{65}’. Si la línea tiene menos de 65 caracteres, la expresiónregular no coincide y la línea no se imprime (dado el switch ‘-n’).

62. Imprimir sólo las líneas que tengan menos de 65 caracteres.sed -n '/^.\{65\}/!p'Este one-liner invierte al anterior. Al utilizar ‘!p’.

Otra forma de realizar lo mismo:sed '/^.\{65\}/d'

63. Imprimir una sección de un archivo desde una expresión regularhasta el final.sed -n '/regexp/,$p'Este one-liner usa ‘/regex/,$’. Si una línea coincide con regex, entonces será impreso elresto del archivo.

64. Imprimir las líneas 8-12 (inclusive) de un archivo.sed -n '8,12p'Este es otro tipo de rango. Se imprime una porción de un archivo entre dos números delínea. Otra forma:sed '8,12!d'

65. Imprimir la línea número 52.sed -n '52p'Este one-liner restringe al comando ‘p’ a la línea 52. Sólo ésta línea se imprime. Y esta esotra forma de hacerlo:sed '52!d'y Aquí otra forma que va eliminando las líneas que no sean la 52 y cuando llega a ésta,sale.sed '52q;d'

66. Comenzar en la línea 3, imprimir cada 7 líneas.gsed -n '3~7p'Este one-liner usa un tipo de ‘salto’. Está pensado para GNU sed (gsed). Comienza en lalínea 3, deja pasar 6 líneas e imprime la septima línea (en este caso la 10 ya que comenzóen la 3), luego deja pasar otras 6 e imprime la siguiente (la 17) y así hasta el final dearchivo.Usando sed, sería:sed -n '3,${p;n;n;n;n;n;n;}'

67. Imprimir una sección de líneas entre dos expresiones regulares(inclusive).sed -n '/Iowa/,/Montana/p'Este one-liner imprime todas las líneas entre la primera línea que coincide con laexpresión regular ‘Iowa’ y la primera línea que coincide con la expresión regular‘Montana’.Usa un rango ‘/start/,/finish/’ mostrando todas las líneas que estén entre las líneas quecoincidan con estas expresiones.Una nota importante sobre los rangos: si ‘start’ y ‘finish’ coinciden sobre la misma línea,esto no funcionará. Por favor leer Sed FAQ 3.3 para mayor información.

Eliminación selectiva de ciertas líneas68. Imprimir todas las líneas en el archivo excepto la sección entre dosexpresiones regulares.sed '/Iowa/,/Montana/d'Este one-liner continua donde el anterior termina. El one-liner #67 de la parte II usa elrango ‘/start/,/finish/’ para imprimir líneas entre dos expresiones regulares (inclusive).Este one-liner, por otro lado, elimina las líneas entre dos expresiones regulares e

imprime el resto. Solo para recordar: un rango ‘/start/,/finish/’ iguala a todas las líneascomenzando desde el principio que igualan a la expresión ‘/start/’ hasta la primer líneaque iguala a ‘/finish/’. En este one-liner en particular, el comando ‘d’ es aplicado a estaslíneas.Por ejemplo, supongamos:FloridaIowaNew YorkSan JoseMontanaTexasFairbanksLuego de que el programa sed termina, la salida sería:FloridaTexasFairbanksVemos esta salida, porque las líneas desde Iowa a Montana coinciden con el rango‘/Iowa/,/Montana/’.

69. Eliminar líneas duplicadas consecutivas de un archivo (emular ‘uniq’).sed '$!N; /^\(.*\)\n\1$/!P; D'Este one-liner actúa como la utilidad ‘uniq’. ¿cómo funciona? Primero, por cada línea queno sea la última, sed agrega la siguiente línea al "pattern space" a través del comando‘N’. Este comando es restringido a todas las líneas excepto la última por el patrón ‘$!’. Lalínea recién agregada es separada de la previa por un caracter ‘\n’. A continuación, el"pattern space" es comparado contra la expresión regular ‘/^\(.*\)\n\1$/’. Esta expresióncaptura la línea anterior hasta el caracter ‘\n’ y la guarda en el grupo ‘\1′. Entonces testeasi la nueva línea agregada es igual a la anterior. Si no lo es, se ejecuta el comando ‘P’imprimiendo todo el "pattern space" hasta el caracter ‘\n’, caso contrario, no se ejecuta.A continuación el comando ‘D’ elimina todo hasta el primer ‘\n’, dejando solo la últimalínea leída en el "pattern space". Además fuerza a sed a ejecutar el script desde el inicio.Veamos un ejemplo:foofoofoobarbarbazLa primera cosa que hace sed es leer la primera línea y ponerla en el "pattern space".Ahora contiene ‘foo’. Luego el comando ‘N’ se ejecuta y el "pattern space"ahora contiene‘foo\nfoo’. A continuación el "pattern space" es testeado nuevamente contra laexpresión regular ‘/^\(.*\)\n\1$/’. Esta expresión coincide porque ‘\(.*\)’ es ‘foo’ y ‘/^\(.*\)\n\1$/’ es ‘foo\nfoo’, tal cual lo que tenemos en el "pattern space". Como coincide, elcomando ‘P’ no es ejecutado y el comando‘D’ entra en ejecución eliminando todo hastael primer ‘\n’ del "pattern space"que hora solo contiene ‘foo’. Sed comienza a ejecutar elscript nuevamente. Se ejecuta ‘N’, el "pattern space" contiene ahora ‘foo\nfoo’nuevamente y las mismas cosas suceden: ‘P’ no se ejecuta y ‘D’ elimina todo hasta ‘\n’dejando en el"pattern space" solo ‘foo’. Nuevamente ‘N’ es ejecutado y esta vez ‘bar’ seagrega al "pattern space" que ahora contiene ‘foo\nbar’. La expresión regular ‘/^\(.*\)\n\1$/’ no coincide y ‘P’ se ejecuta imprimiendo ‘foo’, luego ‘D’ lo borra dejando solo‘bar’. Se reinicia el script y ‘N’ se ejecuta, agrega ‘bar’ con lo cual queda ‘bar\nbar’. Aligual que con ‘foo\nfoo’, no se imprime nada y se repiten los pasos mencionados. Por

último ‘N’ agrega ‘baz’ quedando ‘bar\nbaz’ lo que hace que no coincida la expresiónregular. ‘P’ se ejecuta e imprime y ‘D’ elimina ‘bar’ dejando sólo ‘baz’ en el "patternspace". Ahora ‘N’ no se ejeuta porque es la última línea de entrada. La restricción ‘$!N’ eneste momento hace que las expresiones regulares no coincidan y se imprime el "patternspace" que solo contenía ‘baz’. ‘D’ limpia el "pattern space" y al no haber mas entrada,sed termina.La salida sería:foobarbaz

70. Eliminar líneas duplicadas no consecutivas de un archivo.sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'Este es algo complicado. Almacena las líneas únicas en el hold buffer y por cada nuevalínea leída verifica que no exista en el hold buffer. Si existe, la línea leída es descartada.Si no, es agregada al hold buffer.

71. Elimina todas las líneas excepto las duplicadas consecutivas (emula‘uniq -d’).sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'Este one-liner imprime solo las líneas duplicadas. Comienza leyendo la primera línea conel comando ‘N’. Como se mencionó, la línea actual y la siguiente son separadas con un‘\n’. Además el script restringe el comando ‘N’ a todas las líneas excepto la última. Ahorase intenta una sustitución ‘s/^\(.*\)\n\1$/\1/’. Al igual que en #69, esta sustituciónreemplaza dos cadenas repetidas. Ahora si la sustitución tuvo éxito el comando ‘t’ llevael script a su fin, imprimiendo el"pattern space". Si la sustitución no sucedió se ejecuta‘D’ borrando la cadena no-repetida. El ciclo continúa y sólo las líneas duplicadas sonmostradas una vez.Un ejemplo:foofoobarbazEl resultado sería:fooTal como esperábamos, sólo la línea duplicada es mostrada.

72. Elimina las 10 primeras líneas de un archivo.sed '1,10d'Este one-liner restringe al comando ‘d’ a un rango de líneas. El ’1,10′ indica el rango delíneas de 1 a 10 inclusive. En cada una de estas líneas el comando ‘d’ es ejecutadoborrando el "pattern space" y recomenzando. La acción es que imprimirá todas las líneaspor encima de la décima.

73. Delete the last line of a file.sed '$d'Este one-liner restringe al comando ‘d’ a la última línea. Como resultado, la última líneaes eliminada.

74. Eliminar las últimas dos líneas de un archivo.sed 'N;$!P;$!D;$d'

Este one-liner siempre mantiene dos líneas en el "pattern space". En la última líneasimplemente no muestra estas últimas dos. Tan pronto como sed lee la primer línea en el"pattern space" se ejecuta el primer comando ‘N’. Este coloca la segunda línea en el"pattern space". Los dos siguiente comandos ‘$!P’ y ‘$!D’imprimen la primera parte del"pattern space" hasta ‘\n’ y borra esta parte. Se continúa haciendo lo mismo hasta que laúltima línea es agregada al "pattern space". En este momento ‘$d’ se ejecutaeliminandolas.Si hubiese una sola línea, entonces solo se imprime.

75. Eliminar las últimas 10 líneas de un archivo.sed -e :a -e '$d;N;2,10ba' -e 'P;D'Siempre mantiene 10 líneas en el "pattern space", agregándolas cada nueva y borrandola 11va con ‘D’. Una vez que se alcanza el fin de archivo, ‘d’ borra el"pattern space"eliminando las últimas 10 líneasEsta es otra formased -n -e :a -e '1,10!{P;N;D;};N;ba'

76. Eliminar cada 8 líneas.gsed '0~8d'Este funciona sólo con GNU Sed. Usa una dirección especial que marca una línea como laprimera y salta n pasos. El 0 no es válido. En este caso la primera línea a coincidir será 8,luego 16, luego 24, etc. Cada línea será eliminada por el comando‘d’.Otra forma usando sed sería:sed 'n;n;n;n;n;n;n;d;'

77. Eliminar las líneas que coincidan con un patrón.sed '/pattern/d'Este one-liner ejecuta el comando ‘d’ borrando todas las líneas que coincidancon‘/pattern/’.

78. Borrar todas las líneas en blanco de un archivo (emula “grep ‘.’”).sed '/^$/d'La expresión regular ‘/^$/’ pregunta si es el comienzo de la línea coincide con el final dela misma. Solo las líneas vacías tienen esta propiedad, asi que sed las elimina.Otra forma sería:sed '/./!d'En este caso si la línea coincide al menos con un caracter (representado por ‘.’) esomitida. Si no coincide es porque es una línea vacía y es borrada.

79. Eliminar todas las líneas en blanco consecutivas de un archivo (emula“cat -s”).sed '/./,/^$/!d'En este caso deja una línea en blanco al final del archivo si hubiera muchas. Pero si eso noocurre, todas las líneas en blanco son eliminadas. Usa ‘/start/,/finish/!’ para borrar con ‘d’desde la primer línea en blanco hasta la primera no-vacía, no inclusive.Otra forma:sed '/^$/N;/\n$/D'Si hubiera muchas lineas vacías al principio y al final, este deja solo una al principio y unaal final. En otro caso, elimina todas las consecutivas.

80. Eliminar todas las líneas vacías consecutivas de un archivo exceptolas primeras dos.sed '/^$/N;/\n$/N;//D'En caso de más de 2 líneas vacías, este one-liner las elimina dejando solo dos.Veamos el último comando ‘//D’. Es un atajo a ‘/lo-que-coincidió-anteriormente/D’. Eneste caso ‘/\n$/D’.En cada línea vacía, se agrega al"pattern space" con el comando‘/^$/N’. A continuación se verifica si la línea recién leída es en realidad una línea vacía conel comando ‘/\n$/’. Si lo es, entonces se lee otra línea con ‘N’. En este momento se repiteel mismo test: ‘/\n$/’. Si la línea es vacía, elimina la primera línea en blanco y reinicia elscript desde el principio. Note que hay 2 líneas vacías consecutivas todo el tiempo enel"pattern space". Así, todas las líneas vacías se eliminan dejando solo dos (contenidas enel "pattern space" e impresas al terminar sed).

81. Eliminar todas las líneas vacías al inicio de un archivo.sed '/./,$!d'No hay mucha explicación que dar, hace lo que indica.

82. Elimina todas las líneas vacías al final de un archivo.sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'Este one-liner acumula las líneas vacías en el "pattern space" hasta que encuentra unalínea no-vacía o el final de archivo. Si termina, se ejecuta ‘d’ borrando todo el "patternspace" y termina. Si encuentra una línea no-vacía, el "pattern space" es impreso y elscript continúa. (un caso sería la separación de párrafos con más de una línea en blanco).Para gsed:gsed -e :a -e '/^\n*$/N;/\n$/ba'

83. Eliminar la última línea de cada párrafo.sed -n '/^$/{p;h;};/./{x;/./p;}'Este one-liner siempre mantiene la línea anterior en el hold buffer. Lo consigue a travésdel segundo bloque de comandos ‘/./{x;/./p;}’. En este bloque, el "pattern space" (1línea) es intercambiada con el hold buffer a través del comando ‘x’ y si el hold buffer noestaba vacío se imprime por ‘p’. El siguiente momento a notar es saber que sucede en laprimer línea vacía. Esa es la línea siguiente al párrafo. En este momento ‘/^$/{p;h;}’ esejecutado, se imprime la línea en blanco (pero no imprime la última línea del párrafo!), ycoloca la línea vacía en el hold buffer. Una vez que un nuevo párrafo es alcanzado, elscript se ejecuta nuevamente como si se tratara del primer párrafo.

Aplicaciones Especiales84. Eliminar nroff overstrikes.Nroff overstrikes son caracteres que están formateados para permanecer en negrita. Enlas antiguas máquinas de escribir, uno tipeaba la letra, pulsaba backspace para volver uncaracter y volvía a tipear la letra, remarcándola. En nroff sería CHAR, CTRL+H, CHAR.Este one-liner elimina los CHAR, CTRL+H, dejando simplemente el último CHAR.sed 's/.^H//g'Para insertar el caracter de control Ctrl+H se pulsa Ctrl+V y luego Ctrl+H (asi se inserta^H). Luego se usa el comando de sustitución para borrar cualquier caracter ‘.’ seguido deCtrl+H ^H.Otra manera de hacer lo mismo es usar una expresión de escape en hexadecimal:sed 's/.\x08//g'Incluso existe una manera más, usando el comando echo (note que las comillas invertidas

` ` indican la ejecución de un comando externo a sed y el resultado que arroje seráreemplazado por lo que hay entre las comillas):sed 's/.'`echo -e "\b"`'//g'

85. Imprimir cabecera de mensaje Usenet/HTTP/Email.gsed -r '/^\r?$/q'Las cabeceras de Usenet, HTTP y Email son muy similares. Son un conjunto de líneas detexto, separadas del cuerpo del mensaje con dos nuevas líneas‘\r\n\r\n’. Este one-linertermina en la primer línea que es vacía o contiene ‘\r’. En otras palabras, imprime lacabecera y termina.

86. Imprimri el cuerpo de mensaje Usenet/HTTP/Email.sed '1,/^$/d'Este one-liner usa un rango ’1,/^$/’ para eliminar las líneas desde 1 hasta la última líneaen blanco (inclusive). Como se explicó en el anterior #78, ‘ /^$/’coincide con líneas vacías.Todas las líneas anteriores a la primer línea en blanco son la cabecera y serán borradas.

87. Extraer el Asunto de un mensaje de e-mail.sed '/^Subject: */!d; s///; q'Este one-liner elimina todas las líneas que no coincidan con ‘^Subject: ‘. Luego lo reutiliza‘s///’ para eliminar ‘Subject: ‘ de la línea dejando solamente el asunto real.

88. Extraer información de quién envía de un mensaje de email.sed '/^From: */!d; s///; q'Este one liner es equivalente al anterior, excepto que imprime la información de quienenvía.

89. Extraer una dirección de email de la cadena “Nombre Apellido<[email protected]>”.sed 's/.*< *//;s/ *>.*//;Este one-liner elimina cualquier símbolo antes de < y luego de >.

90. Agrega un > al principio de cada línea (responder a un email).sed 's/^/> /'Este one-liner coloca un caracter ‘>’ al principio de cada línea.

91. Elimina el > inicial de cada línea.sed 's/^> //'Hace justamente lo que indica, además elimina el espacio siguiente al caracter >.

92. Quitar las etiquetas HTML.sed -e :a -e 's/<[^>]*>//g;/</N;//ba'Sed no fue hecho para analizar HTML. Comienza creando una etiqueta ‘a’. Luego en cadalínea sustituye ‘<[^>]*>’ con ningún caracter tantas veces como sea posible (‘g’). Laexpresión ‘<[^>]*>’ indica ‘<’ seguido de cualqueir otro símbolo que no son ‘>’, y quetermina con ‘>’.Disfruta!

Este post completa la tercer parte del artículo Sed en una línea. Espero que hayasaprendido alguna cosa o dos. Fue un placer haberlas explicado.Fin de la traducción.