unix - script - edita el archivo en su lugar
grep (13)
Si está reemplazando la misma cantidad de caracteres y después de leer detenidamente la edición de archivos "en el lugar" ...
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
Desde el Manual de referencia de Bash → 3.6.10 Apertura de descriptores de archivos para lectura y escritura :
El operador de redireccionamiento.
[n]<>word
hace que el archivo cuyo nombre es la expansión de la palabra se abra para leer y escribir en el descriptor de archivos n, o en el descriptor de archivos 0 si no se especifica n. Si no existe el archivo, se crea.
Estoy tratando de averiguar si es posible editar un archivo en un solo comando sed sin transmitir manualmente el contenido editado en un archivo nuevo y luego cambiar el nombre del archivo nuevo al nombre del archivo original. -i
opción -i
pero mi sistema Solaris dijo que -i
es una opción ilegal. ¿Hay alguna forma diferente?
Como dijo Moneypenny en Skyfall: "A veces las mejores maneras son las viejas". Kincade dijo algo similar más tarde.
$ printf '', s / false / true / g / nw / n'' | ed {YourFileHere}
Edición feliz en su lugar. Se agregó ''/ nw / n'' para escribir el archivo. Disculpas por demora respondiendo solicitud.
En un sistema donde sed
no tiene la capacidad de editar archivos, 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 el original porque se ha proporcionado un sufijo / extensión en el lugar vacío.
La opción -i
transmite el contenido editado a un nuevo archivo y, a continuación, le da un nombre tras bambalinas.
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 .
Lo siguiente funciona bien en mi Mac.
sed -i.bak ''s/foo/bar/g'' sample
Estamos reemplazando foo con barra en el archivo de muestra. La copia de seguridad del archivo original se guardará en sample.bak
Para editar en línea sin respaldo, use el siguiente comando
sed -i'''' ''s/foo/bar/g'' sample
Muy buenos ejemplos. Tuve el reto de editar muchos archivos en su lugar y la opción -i parece ser la única solución razonable para usarlo dentro del comando de búsqueda. Aquí el script para agregar "versión:" delante de la primera línea de cada archivo:
find . -name pkg.json -print -exec sed -i ''.bak'' ''1 s/^/version /'' {} /;
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 declarado explícitamente que no desea: escriben en un archivo temporal y luego cambian el nombre del archivo. Pero quizás solo puedas usar ed
. Por ejemplo, para cambiar todas las apariciones 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 quizás debería considerar por qué no quiere usar un archivo temporal cuyo nombre ha cambiado. Incluso si no tiene un -i
compatible con sed
, puede escribir fácilmente un script para que haga el trabajo por usted. En lugar del sed -i ''s/foo/bar/g'' file
, puede hacer inline file sed ''s/foo/bar/g''
. Tal escritura 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.
No especificó qué shell está utilizando, pero con zsh podría usar la construcción =( )
para lograr esto. Algo a lo largo de las líneas de:
cp =(sed ... file; sync) file
=( )
es similar a >( )
pero crea un archivo temporal que se elimina automáticamente cuando cp
termina.
Podrías usar vi
vi -c ''%s/foo/bar/g'' my.txt -c ''wq''
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 de extension
por lo que su comando se analiza realmente como el argumento de extension
y la ruta del archivo se interpreta como el código del comando. Fuente: https://.com/a/19457213
Una cosa a tener en cuenta es que sed
no puede escribir archivos por sí mismo, ya que el único propósito de sed es actuar como 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 en tee
para volver a escribir la salida en el archivo. Otra opción es crear un parche para canalizar el contenido a diff
.
Método de la camiseta
sed ''/regex/'' <file> | tee <file>
Método de parche
sed ''/regex/'' <file> | diff -p <file> /dev/stdin | patch
ACTUALIZAR:
Además, tenga en cuenta que el parche hará que el archivo cambie desde la línea 1 de la salida de 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
sed soporta la edición en el lugar. Del 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 conservar una copia, simplemente no pase el parámetro de extensión.
mv file.txt file.tmp && sed ''s/foo/bar/g'' < file.tmp > file.txt
Debería preservar todos los enlaces físicos, 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.