Encuentra y reemplaza texto dentro de un archivo usando comandos

Respuestas:

1053
sed -i 's/original/new/g' file.txt

Explicación:

  • sed = Stream EDitor
  • -i = in situ (es decir, guardar de nuevo en el archivo original)
  • La cadena de comando:

    • s = el comando sustituto
    • original = una expresión regular que describe la palabra a reemplazar (o solo la palabra misma)
    • new = el texto para reemplazarlo con
    • g = global (es decir, reemplazar todo y no solo la primera aparición)
  • file.txt = el nombre del archivo

cscarney
fuente
3
@ Akiva Si incluye expresiones regulares, los caracteres especiales en su búsqueda sedcoincidirán con ellos. Agregue una -rbandera si desea usar RE extendidos en su lugar.
cscarney
32
@mcExchange Si es específicamente el /carácter que necesita hacer coincidir, puede usar algún otro carácter como separador (por ejemplo 's_old/text_new/text_g'). De lo contrario, puede poner un \ antes de cualquiera $ * . [ \ ^para obtener el carácter literal.
cscarney
3
@BrianZ En lo que respecta al sistema de archivos, la salida de sed es un archivo nuevo con el mismo nombre. Es uno de los errores comúnmente reportados que no son errores
cscarney
17
El comando OSX sed -i '.bak' 's/original/new/g' file.txttambién se puede ejecutar con una extensión de longitud cero sed -i '' 's/original/new/g' file.txt, que no generará respaldo.
Kirk
20
Los usuarios de MacOS deberán agregar '' "después de -i como parámetro para -i ed.gs/2016/01/26/os-x-sed-invalid-command-code para que el archivo se sobrescriba.
geoyws
32

Hay varias formas diferentes de hacer esto. Uno está usando sedy Regex. SED es un editor de secuencias para filtrar y transformar texto. Un ejemplo es el siguiente:

marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog

¡Otra forma que puede tener más sentido que < striny > stroutes con tuberías!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai 
The quick brown fox jumped over the lazy sleeping dog
Marco Ceppi
fuente
66
Tenga caten cat file | sed '...'cuenta que no es necesario. Puedes decir directamente sed '...' file.
fedorqui
1
De hecho, esto se puede reducir aún más: sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarlytomará el archivo yarly y hará los 2 cambios en el lugar mientras realiza una copia de seguridad. Usando el time bash -c "$COMMAND"tiempo sugiere que esta versión es ~ 5 veces más rápida.
pbhj
24

Hay muchas formas de lograrlo. Dependiendo de la complejidad de lo que uno intente lograr con el reemplazo de la cadena, y dependiendo de las herramientas con las que el usuario esté familiarizado, algunos métodos pueden preferirse más que otros.

En esta respuesta estoy usando un input.txtarchivo simple , que puede usar para probar todos los ejemplos proporcionados aquí. El contenido del archivo:

roses are red , violets are blue
This is an input.txt and this doesn't rhyme

GOLPETAZO

Bash no está realmente destinado al procesamiento de texto, pero se pueden hacer sustituciones simples mediante la expansión de parámetros , en particular aquí podemos usar una estructura simple ${parameter/old_string/new_string}.

#!/bin/bash
while IFS= read -r line
do
    case "$line" in
       *blue*) printf "%s\n" "${line/blue/azure}" ;;
       *) printf "%s\n" "$line" ;;
    esac
done < input.txt

Este pequeño script no reemplaza en el lugar, lo que significa que tendría que guardar el texto nuevo en un archivo nuevo y deshacerse del archivo anterior, o mv new.txt old.txt

Nota al margen: si tiene curiosidad sobre por qué while IFS= read -r ; do ... done < input.txtse usa, es básicamente la forma en que Shell lee el archivo línea por línea. Vea esto como referencia.

AWK

AWK, al ser una utilidad de procesamiento de texto, es bastante apropiado para tal tarea. Puede hacer reemplazos simples y mucho más avanzados basados ​​en expresiones regulares . Proporciona dos funciones: sub()y gsub(). El primero solo reemplaza solo la primera ocurrencia, mientras que el segundo reemplaza las ocurrencias en toda la cadena. Por ejemplo, si tenemos una cadena one potato two potato, este sería el resultado:

$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana

$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'                                      
one banana two potato 

AWK puede tomar un archivo de entrada como argumento, por lo input.txtque sería fácil hacer lo mismo con :

awk '{sub(/blue/,"azure")}1' input.txt

Dependiendo de la versión de AWK que tenga, puede o no tener edición en el lugar, por lo tanto, la práctica habitual es guardar y reemplazar texto nuevo. Por ejemplo algo como esto:

awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt

SED

Sed es un editor de línea. También usa expresiones regulares, pero para sustituciones simples es suficiente:

sed 's/blue/azure/' input.txt

Lo bueno de esta herramienta es que tiene edición en el lugar, que puede habilitar con la -ibandera.

Perl

Perl es otra herramienta que a menudo se usa para el procesamiento de texto, pero es un lenguaje de propósito general y se usa en redes, administración de sistemas, aplicaciones de escritorio y muchos otros lugares. Tomó prestados muchos conceptos / características de otros lenguajes como C, sed, awk y otros. La sustitución simple se puede hacer así:

perl -pe 's/blue/azure/' input.txt

Al igual que sed, perl también tiene la bandera -i.

Pitón

Este lenguaje es muy versátil y también se usa en una amplia variedad de aplicaciones. Tiene muchas funciones para trabajar con cadenas, entre las cuales está replace(), por lo que si tiene variables como var="Hello World", podría hacervar.replace("Hello","Good Morning")

La manera simple de leer el archivo y reemplazar la cadena sería:

python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt

Con Python, sin embargo, también necesita generar un archivo nuevo, lo que también puede hacer desde el script. Por ejemplo, aquí hay uno simple:

#!/usr/bin/env python
import sys
import os
import tempfile

tmp=tempfile.mkstemp()

with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
    for line in fd1:
        line = line.replace('blue','azure')
        fd2.write(line)

os.rename(tmp[1],sys.argv[1])

Este script se llamará input.txtcomo argumento de línea de comandos. El comando exacto para ejecutar el script de Python con el argumento de la línea de comandos sería

 $ ./myscript.py input.txt

o

$ python ./myscript.py input.txt

Por supuesto, asegúrese de que ./myscript.pyesté en su directorio de trabajo actual y, por primera vez, asegúrese de que esté configurado como ejecutable conchmod +x ./myscript.py

Python también puede tener expresiones regulares, en particular, hay un remódulo, que tiene una re.sub()función, que se puede usar para reemplazos más avanzados.

Sergiy Kolodyazhnyy
fuente
1
Buena compilación! Otra forma posible que no se menciona aquí es usar el trcomando en Unix
Tapajit Dey
1
@TapajitDey Sí, tr es otra gran herramienta, pero tenga en cuenta que es para reemplazar conjuntos de caracteres (por ejemplo, tr abc cdese traduciría aa c, ba d. Es un poco diferente de reemplazar palabras enteras como sedopython
Sergiy Kolodyazhnyy
22

Puede usar Vim en modo Ex:

ex -s -c '%s/OLD/NEW/g|x' file
  1. % seleccione todas las líneas

  2. s sustituir

  3. g reemplazar todas las instancias en cada línea

  4. x escriba si se han realizado cambios (ellos sí) y salga

Steven Penny
fuente
21

A través del comando gsub de awk,

awk '{gsub(/pattern/,"replacement")}' file

Ejemplo:

awk '{gsub(/1/,"0");}' file

En el ejemplo anterior, todos los 1 se reemplazan por 0 independientemente de la columna donde se encuentra.


Si desea hacer un reemplazo en una columna específica, haga lo siguiente,

awk '{gsub(/pattern/,"replacement",column_number)}' file

Ejemplo:

awk '{gsub(/1/,"0",$1);}' file

Reemplaza 1 con 0 solo en la primera columna.

A través de Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
Avinash Raj
fuente
Usé esto en la terminal de MacOS y no hizo nada ...
Jim
Probado en Alpine Linux (en el contenedor Docker) y no obtuvo salida
Salathiel Genèse
@ SalathielGenèse, ¿qué estás tratando de lograr?
Avinash Raj
Estoy viendo el archivo con inotifywaitunder shenv e informando datos en formato CSV (porque el formato personalizado tiene errores). Entonces pensé que no hay una manera simple de manejar documentos CSV en scripts de shell ... Y lo quiero muy ligero. Entonces comencé un script bastante simple para analizar e informar CSV. Leí las especificaciones de CSV y noté que está más elaborado de lo que esperaba y admite valores multilínea entre comillas dobles. Estaba confiando en la sedtokenización, pero pronto me di cuenta de que incluso lo que sedllaman multilíneas es de hasta dos líneas. ¿Qué sucede si uno de mis valores CSV abarca más de dos líneas?
Salathiel Genèse
Es mejor preguntar su problema como pregunta.
Avinash Raj
8

sedes el s TREAM ed itor , en el que se puede utilizar |(tubería) para enviar flujos estándares (entrada y salida estándar específicamente) a través sedy modificarlos mediante programación sobre la marcha, por lo que es una herramienta muy útil en la filosofía de la tradición Unix; pero también puede editar archivos directamente, utilizando el -iparámetro mencionado a continuación.
Considere lo siguiente :

sed -i -e 's/few/asd/g' hello.txt

s/se utiliza para s ubstitute la expresión que se encuentra fewcon asd:

Los pocos, los valientes.


El asd, el valiente.

/gsignifica "global", lo que significa hacer esto para toda la línea. Si deja de lado /g(con s/few/asd/, siempre debe haber tres barras sin importar qué) y fewaparece dos veces en la misma línea, solo la primera fewse cambia a asd:

Los pocos hombres, las pocas mujeres, los valientes.


Los hombres asd, las pocas mujeres, los valientes.

Esto es útil en algunas circunstancias, como alterar caracteres especiales al comienzo de las líneas (por ejemplo, reemplazar los símbolos mayores que algunas personas usan para citar material anterior en hilos de correo electrónico con una pestaña horizontal mientras deja una desigualdad algebraica citada más adelante en la línea intacto), pero en su ejemplo donde especifica que en cualquier few lugar se debe reemplazar, asegúrese de tenerlo /g.

Las siguientes dos opciones (banderas) se combinan en una sola -ie:

-iopción se utiliza para editar i n coloco en el archivo hello.txt.

-eopción indica el correo Xpression / comando para ejecutar, en este caso s/.

Nota: es importante que utilice -i -epara buscar / reemplazar. Si lo hace -ie, crea una copia de seguridad de cada archivo con la letra 'e' añadida.

Chaminda Bandara
fuente
2

Puedes hacer así:

locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g" 

Ejemplos: para reemplazar todas las ocurrencias [logdir ',' '] (sin []) con [logdir', os.getcwd ()] en todos los archivos que son el resultado del comando de localización, haga lo siguiente:

ex1:

locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"

ex2:

locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"

donde [tensorboard / program.py] es el archivo para buscar

Nguyễn Tuấn Anh
fuente
Hola. Su elección de cadenas ( logdir', ''-> /logdir', os.getcwd()) hace que esta respuesta sea difícil de analizar. Además, vale la pena especificar que su respuesta primero localiza los archivos para usar sed, porque no es parte de la pregunta.
mwfearnley
Hola, esta respuesta es buscar y reemplazar todo si encontró <texto antiguo> en el archivo.
Nguyễn Tuấn Anh
Elijo esta respuesta para todos los que usan el tensorboard en keras, que desean cambiar el comando de: tensorboard --logdir = '/ path / to / log / folder /' para usar: tensorboard solo, cuando permanecen en la carpeta de registros. es muy conveniente
Nguyễn Tuấn Anh