sed editar archivo en su lugar


Estoy tratando de averiguar si es posible editar un archivo en un solo comando sed sin manualmente transmitir el contenido editado a un nuevo archivo y luego cambiar el nombre del nuevo archivo al nombre del archivo original. Probé la opción -i pero mi sistema Solaris dijo que -i es una opción ilegal. ¿Hay una manera diferente?

Author: amphibient, 2012-10-02

13 answers

El -i option transmite el contenido editado a un nuevo archivo y, de todos modos, lo cambia de nombre entre bastidores.

Ejemplo:

sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename

Y

sed -i '' 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename

En macOS .

 267
Author: choroba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-10 12:23:03

En un sistema donde sed no tiene la capacidad de editar archivos en su lugar, creo que la mejor solución sería usar perl:

perl -pi -e 's/foo/bar/g' file.txt

Aunque esto crea un archivo temporal, reemplaza al original porque se ha suministrado un sufijo/extensión vacío en su lugar.

 65
Author: Steve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-03 04:20:22

Tenga en cuenta que en OS X puede obtener errores extraños como "código de comando no válido" u otros errores extraños al ejecutar este comando. Para solucionar este problema intente

sed -i '' -e "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>

Esto se debe a que en la versión OSX de sed, la opción -i espera un argumento extension por lo que su comando se analiza como el argumento extension y la ruta del archivo se interpreta como el código de comando. Fuente: https://stackoverflow.com/a/19457213

 41
Author: diadyne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:30

Lo siguiente funciona bien en mi mac

sed -i.bak 's/foo/bar/g' sample

Estamos reemplazando foo con bar en el archivo de ejemplo. La copia de seguridad del archivo original se guardará en la muestra.bak

Para editar en línea sin copia de seguridad, utilice el siguiente comando

sed -i'' 's/foo/bar/g' sample
 20
Author: minhas23,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-09 08:27:56

Una cosa a tener en cuenta, sed no puede escribir archivos por sí solo, ya que el único propósito de sed es actuar como un editor en el "flujo" (es decir, tuberías de stdin, stdout, stderr y otros >&n buffers, sockets y similares). Con esto en mente, puede usar otro comando tee para escribir la salida de nuevo en el archivo. Otra opción es crear un parche a partir de canalizar el contenido en diff.

Método Ete

sed '/regex/' <file> | tee <file>

Parche método

sed '/regex/' <file> | diff -p <file> /dev/stdin | patch

ACTUALIZACIÓN:

También, tenga en cuenta que patch hará que el archivo cambie desde la línea 1 de la salida diff:

El parche no necesita saber a qué archivo acceder, ya que se encuentra en la primera línea de la salida de diff:

$ echo foobar | tee fubar

$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin
*** fubar   2014-03-15 18:06:09.000000000 -0500
--- /dev/stdin  2014-03-15 18:06:41.000000000 -0500
***************
*** 1 ****
! foobar
--- 1 ----
! fubar

$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin | patch
patching file fubar
 11
Author: Dwight Spencer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-17 08:29:21

No es posible hacer lo que quieras con sed. Incluso las versiones de sed que admiten la opción -i para editar un archivo en su lugar hacen exactamente lo que usted ha indicado explícitamente que no desea: escriben en un archivo temporal y luego cambian el nombre del archivo. Pero tal vez solo puede usar ed. Por ejemplo, para cambiar todas las ocurrencias de foo a bar en el archivo file.txt, puede hacer:

echo ',s/foo/bar/g; w' | tr \; '\012' | ed -s file.txt

La sintaxis es similar a sed, pero ciertamente no es exactamente la misma.

Pero tal vez usted debería considerar por qué no desea usar un archivo temporal renombrado. Incluso si no tiene un -i compatible con sed, puede escribir fácilmente un script para hacer el trabajo por usted. En lugar de sed -i 's/foo/bar/g' file, podrías hacer inline file sed 's/foo/bar/g'. Tal guión es trivial de escribir. Por ejemplo:

#!/bin/sh -e
IN=$1
shift
trap 'rm -f $tmp' 0
tmp=$( mktemp )
<$IN "$@" >$tmp && cat $tmp > $IN  # preserve hard links

Debe ser adecuado para la mayoría de los usos.

 10
Author: William Pursell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-02 19:46:40

Sed admite la edición in situ. De man sed:

-i[SUFFIX], --in-place[=SUFFIX]

    edit files in place (makes backup if extension supplied)

Ejemplo:

Digamos que tienes un archivo hello.txt con el texto:

hello world!

Si desea mantener una copia de seguridad del archivo anterior, use:

sed -i.bak 's/hello/bonjour' hello.txt

Terminarás con dos archivos: hello.txt con el contenido:

bonjour world!

Y hello.txt.bak con el contenido antiguo.

Si no desea mantener una copia, simplemente no pase el parámetro de extensión.

 6
Author: Sergio A.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-22 16:27:51

Podrías usar vi

vi -c '%s/foo/bar/g' my.txt -c 'wq'
 6
Author: mench,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-30 09:04:34
mv file.txt file.tmp && sed 's/foo/bar/g' < file.tmp > file.txt

Debe preservar todos los enlaces duros, ya que la salida se dirige hacia atrás para sobrescribir el contenido del archivo original, y evita cualquier necesidad de una versión especial de sed.

 3
Author: JJM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-08 05:38:51

Si está reemplazando la misma cantidad de caracteres y después de leer cuidadosamente edición"in-place" de archivos...

También puede usar el operador de redirección <> para abrir el archivo para leer y escribir:

sed 's/foo/bar/g' file 1<> file

Verlo en vivo:

$ cat file
hello
i am here                           # see "here"
$ sed 's/here/away/' file 1<> file  # Run the `sed` command
$ cat file
hello
i am away                           # this line is changed now

De Bash Reference Manual → 3.6.10 Apertura de Descriptores de Archivo para Lectura y Escritura :

El operador de redirección

[n]<>word

Hace que el archivo cuyo nombre es la expansión de word sea abierto para lectura y escritura en el descriptor de fichero n, o en el descriptor de fichero 0 si no se especifica n. Si el archivo no existe, se crea.

 3
Author: fedorqui,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-14 14:15:00

No especificó qué shell está utilizando, pero con zsh podría usar la construcción =( ) para lograr esto. Algo parecido a:

cp =(sed ... file; sync) file

=( ) es similar a >( ) pero crea un archivo temporal que se elimina automáticamente cuando cp termina.

 1
Author: Thor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-02 19:09:48

Como dijo Moneypenny en Skyfall: "A veces las viejas costumbres son las mejores." Kincade dijo algo similar más tarde.

Print printf', s / false / true / g\nw\n ' / ed {YourFileHere}

Feliz edición en su lugar. Añadido '\nw\n' para escribir el archivo. Disculpas por la demora en responder a la solicitud.

 0
Author: jlettvin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-18 18:09:07

Muy buenos ejemplos. Tuve el reto de editar en su lugar muchos archivos y la opción-i parece ser la única solución razonable usarlo dentro del comando find. Aquí el script para añadir "version:" delante de la primera línea de cada archivo:

find . -name pkg.json -print -exec sed -i '.bak' '1 s/^/version /' {} \;
 -1
Author: Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-07 11:07:23