GNU/Linux >> Tutoriales Linux >  >> Linux

Primeros pasos con el comando SED [Guía para principiantes]

Sed forma parte de la caja de herramientas estándar de Unix desde finales de los años 60. Como cualquier editor de texto, te ayudará a modificar archivos de texto. Sin embargo, a diferencia de los editores de texto que ya haya utilizado, este no es interactivo.

Eso significa que usted especifica con anticipación las transformaciones que desea aplicar a un archivo y luego la herramienta puede aplicar esas transformaciones sin supervisión.

La mejor descripción de los objetivos de diseño de la herramienta proviene de Lee E. McMahon, el desarrollador central de la implementación original en su artículo sed original:

Sed es un editor de contexto no interactivo que se ejecuta en el sistema operativo UNIX. Sed está diseñado para ser especialmente útil en tres casos:

  1. Para editar archivos demasiado grandes para una edición interactiva cómoda;
  2. Para editar archivos de cualquier tamaño cuando la secuencia de comandos de edición es demasiado complicada para escribirse cómodamente en modo interactivo.
  3. Para realizar múltiples funciones de edición "globales" de manera eficiente en una sola pasada a través de la entrada.

Los diseños de objetivos (1) y (3) probablemente sean menos relevantes con nuestro hardware moderno, pero el segundo sigue siendo válido. Como adición personal, diría que sed es especialmente adecuado para tareas repetitivas, como cuando desea aplicar la misma transformación a un conjunto de archivos.

Aprende los comandos básicos de SED con estos ejemplos

Para darle una idea del poder detrás de sed, consideraré el caso de un desarrollador que necesita agregar un encabezado de licencia encima de cada uno de los archivos fuente en su proyecto:

[email protected]:~$ head MIT.LICENSE *.sh
==> MIT.LICENSE <==
-----8<----------------------------------------------------------------
Copyright <YEAR> <COPYRIGHT HOLDER>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

==> script1.sh <==
#!/bin/bash

echo Hello, I\'m the first script

==> script2.sh <==
#!/bin/bash

cat << EOF
Hello, I'm the second script
EOF

No solo me gustaría ver el archivo de licencia en la parte superior de cada script de shell, sino que también me gustaría que el año y el marcador de posición de derechos de autor se reemplacen por su valor real. Ese será nuestro primer caso de uso.

Nota:si desea practicar por su cuenta, puede descargar los archivos de muestra de mi sitio web. También puede echar un vistazo al vídeo que completa este artículo:

1. Sustitución de texto en SED

En mi archivo de licencia, me gustaría reemplazar los marcadores de posición y por su valor real.

Este es un trabajo perfectamente adecuado para la sustitución de sed dominio. Probablemente el más útil de todos los comandos sed:

[email protected]:~$ sed -e 's/<YEAR>/2018/' MIT.LICENSE  | head -5
-----8<----------------------------------------------------------------
Copyright 2018 <COPYRIGHT HOLDER>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

Usando una tubería (| ), reenvié la salida del comando sed al head herramienta para mostrar solo las primeras cinco líneas aquí. Sin embargo, para nuestro tema específico de hoy, la parte más interesante son los s/<YEAR>/2018/ expresión.

Sed funciona procesando el archivo de entrada una línea a la vez. En cada línea, el sustituto (s ) reemplazará la primera aparición del texto entre las dos primeras barras (/<YEAR>/ ) por el texto entre los dos últimos (/2018/ ). Piense en eso como la función de búsqueda y reemplazo que tiene en un editor de texto GUI.

Vale la pena mencionar aquí que el archivo MIT.LICENSE original no se modificó. Te dejo comprobarlo por ti mismo usando el siguiente comando:

head -5 MIT.LICENSE

2. Reemplazando texto... otra vez

Genial:hemos reemplazado el marcador de posición del año. Pero hay un segundo para reemplazar. Si entendió el ejemplo anterior, probablemente podría imaginar una segunda expresión sed como esta:

's/<COPYRIGHT HOLDER>/Sylvain Leroux/'

Pero, ¿dónde colocar eso? Bueno, tienes varias opciones. La más obvia si ya está familiarizado con el concepto de redirección es canalizar la salida de nuestro primer comando sed a una segunda instancia de sed:

[email protected]:~$ sed -e 's/<YEAR>/2018/' MIT.LICENSE  |
    sed -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' |
    head -5
----8<----------------------------------------------------------------
Copyright 2018 Sylvain Leroux

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

Pero lo podemos hacer mejor. Desde el -e opción introduce una expresión sed, podemos usar varias de ellas como parte de la misma invocación sed, y el resultado será el mismo:

# Pay special attention to the \ at the end of the lines
# specifying the *same* command continues on the
# next line:
sh$ sed -e 's/<YEAR>/2018/'  \
                -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
                MIT.LICENSE |
        head -5

Finalmente, también puede especificar varios comandos en la misma expresión sed separándolos con una nueva línea. Esto es particularmente útil cuando comienza a escribir programas sed más complejos:

# Pay special attention to the single-quotes and
# backslash placement:
sh$ sed -e 's/<YEAR>/2018/
            s/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        MIT.LICENSE |
    head -5

3. Insertar texto

Ahora hemos reemplazado los marcadores de posición por su valor real. Pero todavía tenemos trabajo por hacer antes de poder insertar ese archivo de licencia en los archivos del proyecto. Los que luego son scripts de shell, cada línea de la licencia debe comenzar con un octothorp (# ) para que el shell entienda que no debe intentar interpretar esas líneas.

Para eso, usaremos el comando de sustitución nuevamente. Algo que no mencioné anteriormente es que, contrariamente a la mayoría de las funciones de búsqueda y reemplazo de los editores de GUI, el patrón de búsqueda no es necesariamente la cadena literal a buscar. De hecho, esta es una expresión regular (regex). Eso significa que, además de los caracteres simples que coincidirán literalmente, puede usar caracteres que tendrán un significado especial. Por ejemplo, el signo de intercalación (^ ) representa el comienzo de la línea, el signo de dólar ($ ) el final de la línea o, como último ejemplo, el punto-estrella (.* ) significa cualquier secuencia de 0, 1 o varios caracteres. Hay muchos otros metacaracteres similares, pero por ahora, esto es más que suficiente.

Entonces, para insertar algún texto al principio de una línea, una opción es sustituir el comienzo de la línea por ese texto:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        MIT.LICENSE | head -5
# -----8<----------------------------------------------------------------
# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the

4. Borrando líneas seleccionadas

El comando de sustitución en sed es tan versátil que puede expresar la mayoría de las transformaciones de texto usándolo. Por ejemplo, para eliminar las líneas discontinuas en la parte superior e inferior del texto de la licencia, podría escribir eso:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e 's/^.*----.*$//' \
        MIT.LICENSE | head -5

# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the

Esa sustitución posterior ha reemplazado con la cadena vacía todo el texto:

En resumen, esto reemplazará toda la línea por la cadena vacía si contiene cuatro guiones seguidos. Pero la línea vacía permanece en la salida y aparecerá como una línea en blanco.

Dependiendo de sus necesidades y gustos exactos, también puede considerar la solución alternativa a continuación. Te dejo examinar eso en detalle para señalar los cambios en el comando e identificar por ti mismo cuáles fueron las consecuencias en el resultado:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^.*----.*$//' \
        -e 's/^/# /' \
        MIT.LICENSE | head -5

Si encuentra que la expresión regular utilizada para borrar la línea es demasiado compleja, también podemos beneficiarnos de otra función sed. Casi todos los comandos pueden tener una dirección opcional antes del nombre del comando. Si está presente, limitará el alcance del comando a las líneas coincidencia esa dirección:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e '/----/s/^.*$//' \
        MIT.LICENSE | head -5

Ahora, el último comando de sustitución solo se aplicará a las líneas que coincidan (es decir, que "contengan") cuatro guiones seguidos. Y por cada línea coincidente, reemplazará todo (.* ) entre el inicio (^ ) y fin ($ ) de la línea por la cadena vacía (// )

5. Eliminando líneas seleccionadas

En la sección anterior, modificamos el comando de sustitución para borrar algunas líneas de texto. Pero las líneas vacías permanecieron presentes. A veces esto es deseable. A veces no lo es. En ese último caso, es posible que desee investigar la eliminar comando para eliminar líneas enteras de la salida:

# Below, the redirection '> LICENSE' is used to store
# the result of the sed command into the newly
# created LICENSE file:
[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e '/----/d' \
        MIT.LICENSE > LICENSE
[email protected]:~$ head -5 LICENSE
# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including

El d es el eliminar nombre de comando Al igual que los s fue la sustitución nombre de comando Aquí, especificamos una dirección antes del comando para que solo se eliminen las líneas coincidentes (sin ninguna dirección, la d comando habría borrado cada línea del archivo)

6. Convertir a mayúsculas

Hasta ahora, nos enfocamos principalmente en la parte superior del archivo de licencia. Pero, de hecho, hay algunos cambios que me gustaría realizar un poco más en los documentos. Veamos primero de lo que estoy hablando:

[email protected]:~$ sed -ne '/The above/,$p' LICENSE
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# The software is provided "as is", without warranty of any kind,
# express or implied, including but not limited to the warranties of
# merchantability, fitness for a particular purpose and noninfringement.
# In no event shall the authors or copyright holders be liable for any
# claim, damages or other liability, whether in an action of contract,
# tort or otherwise, arising from, out of or in connection with the
# software or the use or other dealings in the software.

En el comando anterior, usando la opción -n, deshabilité la impresión automática del espacio del patrón. Eso significa que sed ya no imprimirá nada en la salida a menos que se lo pida explícitamente. Esto es exactamente lo que hago con el comando imprimir (p). Observe que en lugar de usar una sola dirección antes del comando p, usé un rango para mostrar el texto entre la línea que contiene el texto "Lo anterior" y el final del documento ($).

El comando de impresión puede ser útil cuando necesita extraer algunas partes de un archivo. Sin embargo, por hoy, solo quería mostrar los últimos dos párrafos para explicar lo que necesito ahora:como es una tradición con los archivos de licencia, me gustaría cubrirme dejando en claro que el software se proporciona "tal cual". Así que me gustaría poner énfasis en el último párrafo (comenzando con "El software") reescribiéndolo todo en mayúsculas.

En la parte de reemplazo de un comando de sustitución, un &se reemplaza por el texto que coincide con el patrón de búsqueda. Usando la extensión \U GNU, podemos cambiar el caso de la cadena de reemplazo:

[email protected]:~$ sed -i -e '/The software/,$s/.*/\U&/' LICENSE
[email protected]:~$ cat LICENSE

En texto plano s/.*/\U&/ significa “reemplazar cualquier texto (.* )por mayúsculas (\U ) versión de sí mismo (& ). Te dejo verificar por ti mismo, el último párrafo ahora debe estar escrito en mayúsculas. Por cierto, te habrás dado cuenta por el -i marca, los cambios se aplicaron directamente al archivo de LICENCIA.

Lo veremos con más detalle en la siguiente sección. Mientras tanto, te dejo practicar y modificar esos comandos a tu voluntad. Una vez que tenga un archivo de licencia que se corresponda con su gusto, será el momento de ver cómo incluirlo antes de cada archivo fuente del proyecto.

7. Insertar un archivo de texto

Si espera algún comando complejo aquí, se sentirá decepcionado:insertar un archivo en otro es bastante sencillo:

sed -i -e '1r LICENSE' script1.sh
cat script1.sh

Dos cosas para ver aquí:

  1. la r LICENSE expresión es el comando para leer e inserte un archivo externo en el archivo que se está procesando actualmente. Tiene el prefijo aquí con el número 1 que es una dirección que coincide solo con la línea 1 del archivo de entrada.
  2. el -i opción permite cambiar un archivo en su lugar . Eso significa que sed creará un archivo temporal detrás de escena para almacenar su salida allí y, una vez que se haya completado el procesamiento, reemplazará el archivo original con el modificado.

Un efecto secundario interesante de la opción '-i' es que puede especificar varios nombres de archivo en la línea de comando, y sed aplicará las mismas transformaciones a cada uno de ellos independientemente :

sed -i -e '1r LICENSE' *.sh

8. Regreso al futuro

Como nuestro último ejemplo del comando sed, imaginemos que han pasado algunos años y ahora somos el 1 de enero de 2024. El aviso de derechos de autor de todos los archivos debe actualizarse. Hay varios casos de uso, dependiendo de cuándo se crearon los archivos del proyecto. Por lo tanto, nuestros avisos de derechos de autor deben seguir uno de estos dos formatos:

Símbolo Descripción
^ Comenzando al principio de la línea
.* Seguido de cualquier secuencia de 0, 1 o varios caracteres
---- Seguido de 4 guiones
.* Seguido de cualquier secuencia de 0, 1 o varios caracteres
$ Seguido por el final de la línea

Podemos capturar esos dos casos de uso a la vez usando una expresión regular extendida (-E). Las únicas cosas "extendidas" que realmente usaremos aquí son los paréntesis:

sed -i -Ee 's/Copyright (....)(-....)?/Copyright \1-2024/' *.sh

Le recomiendo que modifique manualmente el aviso de derechos de autor en los archivos *.sh y luego ejecute el comando anterior en diferentes casos de uso para ver cómo funciona.

Sin embargo, eventualmente podría ayudarlo a comprender si digo, en el patrón de búsqueda:Copyright::es un texto literal que coincidirá palabra por palabra; (… .)::define un grupo de captura que coincide con cuatro caracteres arbitrarios. Ojalá los cuatro dígitos de un año; (-… .)?::define un grupo de captura que coincide con un guión seguido de cuatro caracteres arbitrarios. El signo de interrogación al final indica que el grupo es opcional. Puede o no estar presente en la línea de entrada.

En la cadena de reemplazo:Copyright::es un texto literal que se copiará palabra por palabra; \1::es el contenido del primer grupo de captura -2024::es un texto literal que se copiará palabra por palabra.

Si se tomó el tiempo de verificar el comando usted mismo, debería confirmar si aplico esas reglas a los casos de uso descritos en la tabla anterior, obtendré algo como esto:

Copyright actual Descripción
Derechos de autor 2023 Para archivos creados el año pasado
Derechos de autor 2018-2023 Para archivos creados antes del año pasado

Para concluir nuestra guía SED

Aquí solo hemos arañado la superficie. El sed La herramienta es mucho más poderosa que eso. Sin embargo, incluso si solo hemos visto cuatro comandos (s , p , d y i ) y algunas construcciones básicas de expresiones regulares (^ , $ , . , ? y .* ), ya tienes suficiente conocimiento para resolver muchos problemas del día a día.

Como me gusta terminar un tutorial con un pequeño desafío, esto es lo que te propongo:si has descargado el material de apoyo, encontrarás en el directorio del proyecto un archivo llamado hello.c . Este es el archivo fuente de un programa C básico:

[email protected]:~$ ls
hello.c  MIT.LICENSE  script1.sh  script2.sh
[email protected]:~$ gcc hello.c -o hello
[email protected]:~$ ./hello sylvain
Hello sylvain
[email protected]:~$ cat hello.c

Ya hay algunos comentarios en el archivo fuente. Usándolos como ejemplos de la sintaxis de comentarios en el lenguaje de programación C, ¿podría insertar la licencia MIT en hello.c? archivo fuente usando el comando sed? Puede usar uno o varios comandos sed, puede canalizar la salida de un comando sed a otro, puede usar archivos temporales si lo desea, pero no permitido usar cualquier otro comando que no sea sed. ¡Por supuesto, el archivo fuente C aún debería compilarse después de haber insertado la licencia!

Ahora te dejo pensar en ese pequeño problema y espero que hayas disfrutado ese artículo y el video que lo acompaña. Si quieres saber más sobre sed, ¡háznoslo saber usando la sección de comentarios!


Linux
  1. Comenzando con Zsh

  2. Primeros pasos con el comando tac de Linux

  3. Primeros pasos con el comando cat de Linux

  4. Comenzando con ls

  5. Primeros pasos con PostgreSQL en Linux

Primeros pasos con Nano Text Editor [Guía para principiantes]

Primeros pasos con Markdown [Guía para principiantes]

Primeros pasos con cPanel/WHM

Primeros pasos con AWK Command [Guía para principiantes]

Primeros pasos con Tmux [Guía para principiantes]

Primeros pasos con el comando Tar

    Texto coincidente \1 \2 Cadena de reemplazo
    Derechos de autor 2023 2023 Derechos de autor 2023-2024
    Derechos de autor 2018-2023 2018 -2023 Derechos de autor 2018-2024