Búsqueda de sitios web

Los conceptos básicos del uso del Sed Stream Editor para manipular texto en Linux


Introducción

El comando sed, abreviatura de stream editor, realiza operaciones de edición en el texto proveniente de una entrada estándar o un archivo. sed edita línea por línea y de forma no interactiva.

Esto significa que usted toma todas las decisiones de edición mientras llama al comando, y sed ejecuta las instrucciones automáticamente. Esto puede parecer confuso o poco intuitivo, pero es una forma muy poderosa y rápida de transformar texto, especialmente como parte de un script o flujo de trabajo automatizado.

Este tutorial cubrirá algunas operaciones básicas y le presentará la sintaxis requerida para operar este editor. Es casi seguro que nunca reemplazará su editor de texto regular con sed, pero probablemente se convertirá en una adición bienvenida a su caja de herramientas de edición de texto.

Nota: este tutorial utiliza la versión GNU de sed que se encuentra en Ubuntu y otros sistemas operativos Linux. Si está utilizando macOS, tendrá la versión BSD que tiene diferentes opciones y argumentos. Puede instalar la versión GNU de sed con Homebrew utilizando brew install gnu-sed.

Uso básico

sed opera en un flujo de texto que lee desde un archivo de texto o desde una entrada estándar (STDIN). Esto significa que puede enviar la salida de otro comando directamente a sed para su edición, o puede trabajar en un archivo que ya ha creado.

También debe tener en cuenta que sed envía todo a la salida estándar (STDOUT) de forma predeterminada. Eso significa que, a menos que sea redirigido, sed imprimirá su salida en la pantalla en lugar de guardarla en un archivo.

El uso básico es:

  1. sed [options] commands [file-to-edit]

En este tutorial, utilizará una copia de la licencia de software BSD para experimentar con sed. En Ubuntu, ejecute los siguientes comandos para copiar el archivo de licencia BSD en su directorio de inicio para que pueda trabajar con él:

  1. cd
  2. cp /usr/share/common-licenses/BSD .

Si no tiene una copia local de la licencia BSD, cree una usted mismo con este comando:

  1. cat << 'EOF' > BSD
  2. Copyright (c) The Regents of the University of California.
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions
  6. are met:
  7. 1. Redistributions of source code must retain the above copyright
  8. notice, this list of conditions and the following disclaimer.
  9. 2. Redistributions in binary form must reproduce the above copyright
  10. notice, this list of conditions and the following disclaimer in the
  11. documentation and/or other materials provided with the distribution.
  12. 3. Neither the name of the University nor the names of its contributors
  13. may be used to endorse or promote products derived from this software
  14. without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  16. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  19. FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. SUCH DAMAGE.
  26. EOF

Usemos sed para ver el contenido del archivo de licencia BSD. sed envía sus resultados a la pantalla de forma predeterminada, lo que significa que puede usarlo como un lector de archivos sin pasarle comandos de edición. Prueba a ejecutar el siguiente comando:

  1. sed '' BSD

Verá la licencia BSD en la pantalla:

Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ... ...

Las comillas simples contienen los comandos de edición que pasa a sed. En este caso, no le pasó nada, por lo que sed imprimió cada línea que recibió en la salida estándar.

sed puede usar una entrada estándar en lugar de un archivo. Canaliza la salida del comando cat a sed para producir el mismo resultado:

  1. cat BSD | sed ''

Verá la salida del archivo:

Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . . . . . .

Como puede ver, puede operar en archivos o flujos de texto, como los que se producen al canalizar la salida con el carácter de tubería (|), con la misma facilidad.

Líneas de impresión

En el ejemplo anterior, vio que la entrada pasada a sed sin ninguna operación imprimiría los resultados directamente en la salida estándar.

Exploremos el comando print explícito de sed, que se especifica usando el carácter p entre comillas simples.

Ejecute el siguiente comando:

  1. sed 'p' BSD

Verá cada línea del archivo BSD impresa dos veces:

Output
Copyright (c) The Regents of the University of California. Copyright (c) The Regents of the University of California. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions are met: are met: . . . . . .

sed imprime automáticamente cada línea de forma predeterminada, y luego le indicas que imprima líneas explícitamente con el comando \p, por lo que obtienes cada línea impresa dos veces.

Si examina la salida de cerca, verá que tiene la primera línea dos veces, seguida de la segunda línea dos veces, etc., lo que le indica que sed opera con los datos línea por línea. Lee una línea, opera sobre ella y genera el texto resultante antes de repetir el proceso en la siguiente línea.

Puede limpiar los resultados pasando la opción -n a sed, que suprime la impresión automática:

  1. sed -n 'p' BSD
Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . . . . . .

Ahora volvemos a imprimir cada línea una vez.

Los ejemplos hasta ahora difícilmente pueden considerarse edición (a menos que desee imprimir cada línea dos veces...). A continuación, explorará cómo sed puede modificar la salida dirigiéndose a secciones específicas de los datos de texto.

Uso de rangos de direcciones

Las direcciones le permiten dirigirse a partes específicas de un flujo de texto. Puede especificar una línea específica o incluso un rango de líneas.

Hagamos que sed imprima la primera línea del archivo. Ejecute el siguiente comando:

  1. sed -n '1p' BSD

La primera línea se imprime en la pantalla:

Output
Copyright (c) The Regents of the University of California.

Al colocar el número 1 antes del comando de impresión, le indicaste a sed el número de línea para operar. Puede imprimir fácilmente cinco líneas (no olvide el \-n):

  1. sed -n '1,5p' BSD

Verás este resultado:

Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions

Acabas de dar un rango de direcciones a sed. Si le das a sed una dirección, solo ejecutará los comandos que siguen en esas líneas. En este ejemplo, le ha dicho a sed que imprima de la línea 1 a la línea 5. Podría haber especificado esto de otra manera dando la primera dirección y luego usando un desplazamiento para decirle a sed cuántas líneas adicionales debe viajar, así:

  1. sed -n '1,+4p' BSD

Esto dará como resultado el mismo resultado, porque le dijiste a sed que comenzara en la línea 1 y luego operara también en las siguientes 4 líneas.

Si desea imprimir líneas alternas, especifique el intervalo después del carácter ~. El siguiente comando imprime líneas alternas en el archivo BSD, comenzando con la línea 1:

  1. sed -n '1~2p' BSD

Aquí está el resultado que verá:

Output
Copyright (c) The Regents of the University of California. modification, are permitted provided that the following conditions 1. Redistributions of source code must retain the above copyright 2. Redistributions in binary form must reproduce the above copyright documentation and/or other materials provided with the distribution. may be used to endorse or promote products derived from this software . . . . . .

También puede usar sed para eliminar texto de la salida.

Eliminación de texto

Puede realizar la eliminación de texto donde anteriormente especificaba la impresión de texto cambiando el comando p al comando d.

En este caso, ya no necesita el comando -n porque sed imprimirá todo lo que no se elimine. Esto le ayudará a ver lo que está pasando.

Modifique el último comando de la sección anterior para que sea

  1. sed '1~2d' BSD

El resultado es que ves todas las líneas que no te dieron la última vez:

Output
All rights reserved. Redistribution and use in source and binary forms, with or without are met: notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the 3. Neither the name of the University nor the names of its contributors without specific prior written permission. . . . . . .

Es importante tener en cuenta aquí que nuestro archivo fuente no se ve afectado. Todavía está intacto. Las ediciones se envían a nuestra pantalla.

Si queremos guardar nuestras ediciones, podemos redirigir la salida estándar a un archivo como este:

  1. sed '1~2d' BSD > everyother.txt

Ahora abre el archivo con cat:

  1. cat everyother.txt

Verá el mismo resultado que vio en pantalla anteriormente:

Output
All rights reserved. Redistribution and use in source and binary forms, with or without are met: notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the 3. Neither the name of the University nor the names of its contributors without specific prior written permission. . . . . . .

El comando sed no edita el archivo fuente de manera predeterminada, pero puede cambiar este comportamiento pasando la opción -i, lo que significa \realizar ediciones en el lugar. Esto alterará el archivo fuente.

Advertencia: Usar el modificador -i sobrescribirá el archivo original, por lo que debe usarlo con cuidado. Realice las operaciones sin el interruptor -i primero y luego ejecute el comando nuevamente con -i una vez que tenga lo que desea, cree una copia de seguridad del archivo original o redirija el salida a un archivo. Es muy fácil alterar accidentalmente el archivo original con el interruptor -i.

Intentémoslo editando el archivo everyother.txt que acabas de crear, en el lugar. Reduzcamos aún más el archivo eliminando una línea por medio

  1. sed -i '1~2d' everyother.txt

Si usa cat para mostrar el archivo con cat everyother.txt, verá que el archivo ha sido editado.

La opción -i puede ser peligrosa. Afortunadamente, sed te permite crear un archivo de respaldo antes de editarlo.

Para crear un archivo de respaldo antes de editarlo, agregue la extensión de respaldo directamente después de la opción \-i:

  1. sed -i.bak '1~2d' everyother.txt

Esto crea un archivo de respaldo con la extensión .bak y luego edita el archivo original en el lugar.

A continuación, verá cómo usar sed para realizar operaciones de búsqueda y reemplazo.

Sustitución de texto

Quizás el uso más conocido de sed es sustituir texto. sed puede buscar patrones de texto usando expresiones regulares y luego reemplazar el texto encontrado con otra cosa.

Puede obtener más información sobre las expresiones regulares siguiendo el Uso de expresiones regulares Grep para buscar patrones de texto en Linux.

En su forma más básica, puede cambiar una palabra por otra usando la siguiente sintaxis:

's/old_word/new_word/'

El s es el comando sustituto. Las tres barras (/) se utilizan para separar los diferentes campos de texto. Puede usar otros caracteres para delimitar los campos si le resulta más útil.

Por ejemplo, si estuviera tratando de cambiar el nombre de un sitio web, sería útil usar otro delimitador ya que las URL contienen barras.

Ejecute el siguiente comando para imprimir una URL con echo y modificarla con sed, utilizando el carácter de subrayado (_) como delimitador:

  1. echo "http://www.example.com/index.html" | sed 's_com/index_org/home_'

Esto reemplaza com/index con org/home. El resultado muestra la URL modificada:

Output
http://www.example.org/home.html

No olvide el delimitador final, o sed se quejará. Si ejecutó este comando:

  1. echo "http://www.example.com/index.html" | sed 's_com/index_org/home'

Verías este resultado:

Output
sed: -e expression #1, char 20: unterminated `s' command

Vamos a crear un nuevo archivo para practicar algunas sustituciones. Ejecute el siguiente comando para crear un nuevo archivo de texto llamado song.txt:

  1. echo "this is the song that never ends
  2. yes, it goes on and on, my friend
  3. some people started singing it
  4. not knowing what it was
  5. and they'll continue singing it forever
  6. just because..." > song.txt

Ahora sustituyamos la expresión on por forward. Usa el siguiente comando:

  1. sed 's/on/forward/' song.txt

La salida se ve así:

Output
this is the sforwardg that never ends yes, it goes forward and on, my friend some people started singing it not knowing what it was and they'll cforwardtinue singing it forever just because...

Puedes ver algunas cosas notables aquí. Primero, es que sed reemplazó patrones, no palabras. El on dentro de song se cambia a forward.

La otra cosa a tener en cuenta es que en la línea 2, el segundo on no se cambió a forward.

Esto se debe a que, de manera predeterminada, el comando s opera en la primera coincidencia de una línea y luego pasa a la siguiente línea. Para hacer que sed reemplace cada instancia de on en lugar de solo la primera en cada línea, debe pasar una marca opcional al comando de sustitución.

Proporcione el indicador g al comando de sustitución colocándolo después del conjunto de sustitución:

  1. sed 's/on/forward/g' song.txt

Verás este resultado:

Output
this is the sforwardg that never ends yes, it goes forward and forward, my friend some people started singing it not knowing what it was and they'll cforwardtinue singing it forever just because...

Ahora el comando sustituto cambia cada instancia.

Si solo quisiera cambiar la segunda instancia de \on” que sed encuentra en cada línea, entonces usaría el número 2 en lugar de g:

  1. sed 's/on/forward/2' song.txt

Esta vez, las otras líneas no cambian, ya que no tienen una segunda aparición:

Output
this is the song that never ends yes, it goes on and forward, my friend some people started singing it not knowing what it was and they'll continue singing it forever just because...

Si solo desea ver qué líneas se sustituyeron, use la opción -n nuevamente para suprimir la impresión automática.

Luego puede pasar la opción p al comando de sustitución para imprimir líneas donde se realizó la sustitución.

  1. sed -n 's/on/forward/2p' song.txt

La línea que cambió se imprime en la pantalla:

Output
yes, it goes on and forward, my friend

Como puede ver, puede combinar las banderas al final del comando.

Si desea que el proceso de búsqueda ignore las mayúsculas y minúsculas, puede pasarle el indicador \i.

  1. sed 's/SINGING/saying/i' song.txt

Aquí está el resultado que verá:

Output
this is the song that never ends yes, it goes on and on, my friend some people started saying it not knowing what it was and they'll continue saying it forever just because...

Reemplazar y hacer referencia al texto coincidente

Si desea encontrar patrones más complejos con expresiones regulares, tiene varios métodos diferentes para hacer referencia al patrón coincidente en el texto de reemplazo.

Por ejemplo, para hacer coincidir desde el principio de la línea con at, use el siguiente comando:

  1. sed 's/^.*at/REPLACED/' song.txt

Verás este resultado:

Output
REPLACED never ends yes, it goes on and on, my friend some people started singing it REPLACED it was and they'll continue singing it forever just because...

Puede ver que la expresión comodín coincide desde el principio de la línea hasta la última instancia de at.

Como no sabe la frase exacta que coincidirá en la cadena de búsqueda, puede usar el carácter & para representar el texto coincidente en la cadena de reemplazo.

Pongamos paréntesis alrededor del texto coincidente:

  1. sed 's/^.*at/(&)/' song.txt

Verás este resultado:

Output
(this is the song that) never ends yes, it goes on and on, my friend some people started singing it (not knowing what) it was and they'll continue singing it forever just because...

Una forma más flexible de hacer referencia al texto coincidente es usar paréntesis de escape para agrupar secciones de texto coincidente.

Cada grupo de texto de búsqueda marcado con paréntesis puede ser referenciado por un número de referencia con escape. Por ejemplo, se puede hacer referencia al primer grupo de paréntesis con , al segundo con y así sucesivamente.

En este ejemplo, cambiaremos las dos primeras palabras de cada línea:

  1. sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/' song.txt

Verás este resultado:

Output
is this the song that never ends yes, goes it on and on, my friend people some started singing it knowing not what it was they and'll continue singing it forever because just...

Como puedes ver, los resultados no son perfectos. Por ejemplo, la segunda línea salta la primera palabra porque tiene un carácter que no figura en nuestro conjunto de caracteres. De manera similar, trató a theyll como dos palabras en la quinta línea.

Mejoremos la expresión regular para que sea más precisa:

  1. sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/\2 \1/' song.txt

Verás este resultado:

Output
is this the song that never ends it yes, goes on and on, my friend people some started singing it knowing not what it was they'll and continue singing it forever because... just

Esto es mucho mejor que la última vez. Esto agrupa la puntuación con la palabra asociada.

Observe cómo repetimos la expresión dentro de los paréntesis (una vez sin el carácter * y luego otra vez con él). Esto se debe a que el carácter * coincide con el conjunto de caracteres anterior cero o más veces. Esto significa que la coincidencia con el comodín se consideraría una coincidencia incluso si no se encuentra el patrón.

Para asegurarse de que sed encuentre el texto al menos una vez, debe hacerlo coincidir una vez sin el comodín antes de emplear el comodín.

Conclusión

En este tutorial, exploró el comando sed. Imprimió líneas específicas del archivo, buscó texto, eliminó líneas, sobrescribió el archivo original y usó expresiones regulares para reemplazar el texto. Ya debería poder ver cómo puede transformar rápidamente un documento de texto utilizando comandos sed construidos correctamente.

En el próximo artículo de esta serie, explorará algunas características más avanzadas.