Linux: Reemplazar texto en archivos con sed

Si queremos buscar y reemplazar texto en entornos Linux, disponemos de varias herramientas para ello.

Una de ellas es con el comando sed.

Linux SED: Reemplazar texto en archivos con sed

El comando sed está presente en la mayoría de distribuciones de Linux y está pensado para manipular cadenas de texto.

Si no disponemos del comando sed lo podemos instalar de la siguiente forma:

  • Para CentOS/RHEL: yum install sed
  • Para Debian/Ubuntu: apt-get install sed

Sintaxis general y tres ejemplos para reemplazar texto en archivos:

Sintaxis general:

sed -i 's/texto-a-buscar/texto-a-reemplazar/g' "Fichero o directorio"

Ejemplo 1: Cambiamos el texto Sysadmit por SYSADMIT del interior del fichero: test.txt

[root@LINUX1 test]# cat test.txt
Sysadmit1
1Sysadmit
90Sysadmit82
HSysadmitH21
 
[root@LINUX1 test]# sed -i 's/Sysadmit/SYSADMIT/g' "test.txt"
 
[root@LINUX1 test]# cat test.txt
SYSADMIT1
1SYSADMIT
90SYSADMIT82
HSYSADMITH21

Ejemplo 2: Cambiamos el texto SYSADMIT por --SYSADMIT-- en todos los ficheros *.txt a partir de la ruta /test/ de forma recursiva.

Para ello utilizaremos los siguientes comandos:

find: Nos realizará una búsqueda de todos los ficheros según el patrón definido.
xargs: Ejecutará un comando (en este caso sed) para cada resultado generado por el comando find.
| : Pipe o tubería, en este caso la salida de find corresponderá a la entrada de sed.
sed: Realizará el "buscar-reemplazar".

[root@LINUX1 test]# pwd
/test

[root@LINUX1 test]# du -ah
4.0K    ./new/test.txt
8.0K    ./new
4.0K    ./test.txt
16K     .

[root@LINUX1 test]# cat ./new/test.txt
SYSADMIT1
1SYSADMIT
90SYSADMIT82
HSYSADMITH21

[root@LINUX1 test]# cat ./test.txt
SYSADMIT1
1SYSADMIT
90SYSADMIT82
HSYSADMITH21

[root@LINUX1 test]# find /test/ -name "*.txt" -print | xargs sed -i "s/SYSADMIT/--SYSADMIT--/g"

[root@LINUX1 test]# cat ./new/test.txt
--SYSADMIT--1
1--SYSADMIT--
90--SYSADMIT--82
H--SYSADMIT--H21

[root@LINUX1 test]# cat ./test.txt
--SYSADMIT--1
1--SYSADMIT--
90--SYSADMIT--82
H--SYSADMIT--H21


Ejemplo 3: Cambiamos una URL por otra del interior de un fichero de texto (test.txt).

El problema de las URLs es que contienen el carácter: "/".

El carácter "/", sed lo utiliza para definir el texto original y el texto a reemplazar.

En el siguiente ejemplo, reemplazaremos la URL:

http://sysadmit.com

por:

http://www.sysadmit.com/p/faq-libros.html

dentro del fichero: test.txt

Para ello, utilizaremos el caracter: "%"

[root@LINUX1 test]# cat test.txt
http://sysadmit.com

[root@LINUX1 test]# sed -i "s%http://sysadmit.com%http://www.sysadmit.com/p/faq-libros.html%g" "test.txt"


[root@LINUX1 test]# cat test.txt
http://www.sysadmit.com/p/faq-libros.html

 

24 comentarios:

  1. Gracias!.

    Buen tutorial!.

    Saludos,

    ResponderEliminar
    Respuestas
    1. ¡Gracias a ti! ¡Me alegro que te haya gustado!

      Un saludo,

      Xavi.

      Eliminar
  2. Excelente!!!, tengo un problema, necesito reemplazar solo una vez en el archivo (la primera vez)

    Me explico, para el caso del ejemplo, si el archivo fuera
    Sysadmit
    Sysadmit
    Sysadmit

    después de ejecutar el comando que indicas (sed -i 's/Sysadmit/SYSADMIT/g' "test.txt") quedaría:
    SYSADMIT
    SYSADMIT
    SYSADMIT

    Pero yo necesito que quede:
    SYSADMIT
    Sysadmit
    Sysadmit

    ¿es posible hacer eso?

    ResponderEliminar
    Respuestas
    1. Hola Andrés,

      Aquí tienes como hacerlo:

      [root@LINUX1]# cat test.txt
      Sysadmit
      Sysadmit
      Sysadmit

      [root@LINUX1]# sed -i '0,/Sysadmit/ s//SYSADMIT/' "test.txt"

      [root@LINUX1]# cat test.txt
      SYSADMIT
      Sysadmit
      Sysadmit

      ¡¡Un saludo!!

      Xavi.

      Eliminar
    2. Xavi,
      es justo lo que necesitaba.

      muchas gracias!.

      Eliminar
    3. ¡Gracias a ti!

      ¡Un saludo!

      Xavi.

      Eliminar
  3. Hola! Necesito hacer sed s/patron1/patron2/g file.txt > filefinal. El tema es que patron 1 y patron 2 corresponden a col 1 y col 2 de otro archivo (index.txt). Cómo hago referencia a esas columnas y cómo le pido que repita el procedimiento desde la primer hasta la última fila? Gracias!

    ResponderEliminar
    Respuestas
    1. Hola Matias,

      Lo puedes hacer con este comando: sed s/`cat index.txt|awk '{ print $1 }'`/`cat index.txt |awk '{ print $2 }'`/g file.txt > final.txt

      el secreto está en dónde hay patrón1 / patrón2 ejecutar un comando de awk: `cat index.txt|awk '{ print $1 }'`


      Ejemplo para probarlo:

      [root@SYSADMIT.LAB 2]# ls
      file.txt index.txt
      [root@SYSADMIT.LAB 2]# cat index.txt
      Columna1 Columna2
      [root@SYSADMIT.LAB 2]# cat file.txt
      Columna1
      Columna1
      Columna1
      Columna1
      Columna1
      Columna1
      Columna1
      Columna1
      [root@SYSADMIT.LAB 2]# sed s/`cat index.txt|awk '{ print $1 }'`/`cat index.txt |awk '{ print $2 }'`/g file.txt
      Columna2
      Columna2
      Columna2
      Columna2
      Columna2
      Columna2
      Columna2
      Columna2
      [root@SYSADMIT.LAB 2]# sed s/`cat index.txt|awk '{ print $1 }'`/`cat index.txt |awk '{ print $2 }'`/g file.txt > final.txt
      [root@SYSADMIT.LAB 2]# cat final.txt
      Columna2
      Columna2
      Columna2
      Columna2
      Columna2
      Columna2
      Columna2
      Columna2

      Eliminar
  4. Muy bueno, lo uso también en bash del macOS

    ResponderEliminar
  5. Hola que tal tengo un problema necesito sustituir una cadena así:
    exten => _77[0-9]00[1-6],1,MixMonitor(/home/site/${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}-${EXTEN}-${CALLERID(num)}.wav)

    y lo intento así:

    sed -i "s%exten => _77[0-9]00[1-6],1,MixMonitor(/home/site/${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}-${EXTEN}-${CALLERID(num)}.wav)%hola%g" "extensions001.conf"

    Aqui en el ejemplo quiero sustituirlo por hola, pero enrealidad seria por:
    exten => _77[0-9]00[1-6],1,MixMonitor(/home/site/cabina1/${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}-${EXTEN}-${CALLERID(num)}.wav)

    Pero cuando lo intento me dice:

    -bash: s%exten => _77[0-9]00[1-6],1,MixMonitor(/home/site/${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}-${EXTEN}-${CALLERID(num)}.wav)%hola%g: sustitución errónea

    Podrias ayudarme ..... Saludos.

    ResponderEliminar
  6. Hola! necesito sustituir
    SYSADMIT
    SYSADMIT
    SYSADMIT
    por
    SYSADMIT1
    SYSADMIT2
    SYSADMIT3
    Podrían ayudarme! Gracias!

    ResponderEliminar
  7. Hola, Tengo un archivo con doble salto de linea \n\n y necesito que quede solo con un salto de linea, el archivo luce asi:

    752

    3165545715

    225

    680

    Intente :

    sed 's/\n\n/\n/g' archivo.txt

    pero no funcionó

    ResponderEliminar
  8. Incluso a pesar de que a primera vista no me resultó muy amigable para leer, lo leí y... ¡me pareció excelente!
    ¡Muchas gracias!

    ResponderEliminar
  9. Hola Quisiera pedirte apoyo. estoy ejecutando el sed

    sed -i 's/'"("'/'"(Total = "'/g' archivo.txt

    el archivo.txt fue creado por un usuario con mas privilegios y debo ejecutar la sentencia con un usuario de explotación.

    el usuario de explotación funciona con archivos creados bajo su mismo usr, pero no me deja con los archivos creados con otro usuario.

    Como se puede ejecutar para que lo realice igual?

    El error que da: sed: cannot rename ./sedr2pm9K: Operation not permitted

    el archivo esta con permisos 777 y la ruta donde esta el archivo tambien.

    ResponderEliminar
    Respuestas
    1. Hola,

      ¿Tienes SELinux activado?

      - Para verificar el estado de SELinux:

      getenforce

      - Para deshabilitar SELinux:

      Editar el fichero: /etc/selinux/config

      Configurar: SELINUX=disabled

      Es necesario reiniciar el equipo para que se aplique la configuración.

      Un saludo,

      Xavi.

      Eliminar
  10. Hola,
    no sé como puedo reemplazar una palabra en común en varios archivos del fichero.

    Ejemplo estaba en la versión 6 y dentro de esta carpeta todos los archivos apuntan a /v6/ejemplo y quiero hacer una copia del fichero version6 a version7 y que en version7 todos los archivos que apuntan a v6/ejemplo apunten a /v7/ejemplo

    ResponderEliminar
    Respuestas
    1. Hola,

      Con el comando find puedes utilizar sed para reemplazar en varios ficheros.

      En este mismo post tienes un ejemplo:

      find /test/ -name "*.txt" -print | xargs sed -i "s/SYSADMIT/--SYSADMIT--/g"

      Un saludo,

      Xavi.

      Eliminar
  11. Hola, estoy intentando hacer un script que realice lo siguiente:

    Dado dos archivos
    en archivo1 tengo:

    [seccion1]
    A=def
    B=def
    C=def

    [seccion2]
    A=def
    B=def

    [seccion3]
    A=def

    Y en el archivo2, tengo

    [seccion1]
    A=loc
    B=loc
    C=loc

    [seccion2]
    B=loc

    Y me gustaría como objetivo final, tener el archivo2 modificado con esta forma

    [seccion1]
    A=loc
    B=def
    C=def

    [seccion2]
    A=def
    B=loc

    [seccion3]
    A=def

    Se me complica poder recorrer las secciones por indice y poder compararlas entre los archivos, además de que tengo que ver si tienen los mismos settings o distintos

    La idea es que dados dos archivos de configuraciones, sobre escribir las cosas de uno en el otro con determinados criterios.
    Si alguien puede ayudarme me vendría bien! gracias

    ResponderEliminar
  12. Buenos días, necesito reemplazar el contenido entre dos etiquetas que no están en la misma linea de un XML, como lo puedo hacer?

    Lo he intentado con sed -i.BAK 's@\(<'parameterizedSpecification'>\).\+\(\)@\1'" TEXT1 \n TEXT2 \n "'\2@' /tmp/pepe.xml

    pero solo funciona si el tag está en la misma linea.

    Este es el ejemplo del XML
    #https://en.wikipedia.org/wiki/Cron#CRON_expression
    #REINICIO LOS LUNES A PETICION DE PROYECTO
    #00 7 * * 1 % AUTOMATIC_RUN=true;BUILD_NUM=1;ENVIRON=$ENVIRON;ACTION=RESTART;SERVICE=ALL;REMOTEDEBUGMODE=true



    Gracias

    ResponderEliminar
  13. Mil gracias, muy bien explicado.

    ResponderEliminar