Estoy tratando de averiguar si es posible editar un archivo en un solo comando sed sin transmitir manualmente el contenido editado a un nuevo archivo y luego renombrar el nuevo archivo al nombre del archivo original. Probé la -i
opción pero mi sistema Solaris dijo que -i
es una opción ilegal. ¿Hay una manera diferente?
300
-i
es una opción en gnu sed, pero no está en sed estándar. Sin embargo, transmite el contenido a un nuevo archivo y luego cambia el nombre del archivo para que no sea lo que desea.Respuestas:
La
-i
opción transmite el contenido editado a un nuevo archivo y luego lo renombra detrás de escena, de todos modos.Ejemplo:
y
en macOS .
fuente
sed -i "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
En un sistema donde
sed
no tiene la capacidad de editar archivos en su lugar, creo que la mejor solución sería usarperl
:Aunque esto crea un archivo temporal, reemplaza el original porque se ha proporcionado un sufijo / extensión vacío.
fuente
sudo
. En mi opinión, la pregunta es sobre cómo evitar crear y renombrar manualmente un archivo temporal sin tener que instalar el último GNU o BSDsed
. Solo usa Perl.sed 's/foo/bar/g' file.txt > file.tmp && mv file.tmp file.txt
. El hecho de que la edición in situ cambie el nombre utilizando un archivo temporal, no significa que deba realizar un cambio de nombre manual cuando la opción no está disponible. Existen otras herramientas que pueden hacer lo que él / ella quiere, y Perl es la opción obvia. ¿Cómo es que esto no es una respuesta a la pregunta original?sed
. La pregunta fue realmente muy buena, pero su valor ha sido disminuido por personas que no pueden leer las páginas de manual o no pueden molestarse en leer las preguntas aquí en SO.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
Esto se debe a que en la versión OSX de
sed
, la-i
opción espera unextension
argumento, por lo que su comando se analiza realmente como elextension
argumento y la ruta del archivo se interpreta como el código del comando. Fuente: https://stackoverflow.com/a/19457213fuente
brew install gnu-sed
junto con aPATH
le permitirá usar la versión GNU de sed. Gracias por mencionarlo; Un definitivo rascador de cabeza.Lo siguiente funciona bien en mi mac
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
fuente
Una cosa a tener en cuenta
sed
es que no puede escribir archivos por sí solo, ya que el único propósito de sed es actuar como editor en la "secuencia" (es decir, las tuberías de stdin, stdout, stderr y otros>&n
buffers, sockets y similares). Con esto en mente, puede usar otro comandotee
para volver a escribir la salida en el archivo. Otra opción es crear un parche para canalizar el contenidodiff
.Método de la camiseta
Método de parche
ACTUALIZAR:
Además, tenga en cuenta que el parche hará que el archivo cambie desde la línea 1 de la salida diff:
Patch no necesita saber a qué archivo acceder, ya que se encuentra en la primera línea de la salida de diff:
fuente
/dev/stdin 2014-03-15
, respondió el 7 de enero - ¿eres un viajero del tiempo?/dev/stdin
no existe, por lo que debe reemplazarlo/dev/stdin
con '-', un solo guión sin las comillas, por lo que los siguientes comandos deberían funcionar:$ sed 's/oo/u/' fubar | diff -p fubar -
y$ sed 's/oo/u/' fubar | diff -p fubar - | patch
patch
no se truncará también. Creo que guardar la salida en otro archivo y luegocat
convertirlo en original sería más seguro.No es posible hacer lo que quieres con
sed
. Incluso las versionessed
que admiten la-i
opción de editar un archivo en el 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 tal vez solo puedas usared
. Por ejemplo, para cambiar todas las apariciones defoo
abar
en el archivofile.txt
, puede hacer lo siguiente:La sintaxis es similar
sed
, pero ciertamente no es exactamente la misma.Pero quizás debería considerar por qué no desea utilizar un archivo temporal renombrado. Incluso si no tiene un
-i
soportesed
, puede escribir fácilmente un script para hacer el trabajo por usted. En vez desed -i 's/foo/bar/g' file
, podrías hacerinline file sed 's/foo/bar/g'
. Tal guión es trivial de escribir. Por ejemplo:debe ser adecuado para la mayoría de los usos.
fuente
inline
e invocaría como se describe arriba:inline inputfile sed 's/foo/bar/g'
ed
solo responde que realmente funciona en el lugar. Primera vez que necesitoed
. Gracias. Se debe utilizar una pequeña optimizaciónecho -e ",s/foo/bar/g\012 w"
oecho $',s/foo/bar/g\012 w'
donde shell le permite evitartr
llamadas adicionales .ed
realmente no hace las modificaciones en el lugar. Desde lastrace
salida, GNUed
crea un archivo temporal, escribe los cambios en el archivo temporal, luego reescribe todo el archivo original, conservando los enlaces duros. Desde latruss
salida, Solaris 11ed
también usa un archivo temporal, pero cambia el nombre del archivo temporal al nombre del archivo original al guardar con elw
comando, destruyendo los enlaces duros.ed
que se envía con los macos actuales (Mojave, sea lo que sea que signifique esa jerga de marketing) aún conserva los enlaces duros. YMMVPodrías usar vi
fuente
sed admite la edición en el lugar. De
man sed
:Ejemplo :
Digamos que tiene un archivo
hello.txt
con el texto:Si desea mantener una copia de seguridad del archivo anterior, use:
Terminarás con dos archivos:
hello.txt
con el contenido:y
hello.txt.bak
con el viejo contenido.Si no desea conservar una copia, simplemente no pase el parámetro de extensión.
fuente
No especificó qué shell está utilizando, pero con zsh podría usar la
=( )
construcción para lograr esto. Algo en la línea de:=( )
es similar>( )
pero crea un archivo temporal que se elimina automáticamente cuandocp
finaliza.fuente
Debe preservar todos los enlaces duros, ya que la salida se dirige hacia atrás para sobrescribir el contenido del archivo original, y evita la necesidad de una versión especial de sed.
fuente
Si está reemplazando la misma cantidad de caracteres y después de leer detenidamente la edición "in situ" de los archivos ...
También puede usar el operador de redirección
<>
para abrir el archivo para leer y escribir:Véalo en vivo:
Del Manual de referencia de Bash → 3.6.10 Abrir descriptores de archivos para leer y escribir :
fuente
Como dijo Moneypenny en Skyfall: "A veces las viejas formas son las mejores". Kincade dijo algo similar más tarde.
Feliz edición en su lugar. Se agregó '\ nw \ n' para escribir el archivo. Disculpas por retrasar la solicitud de respuesta.
fuente
|
. @MattMontag\n
. [rango] s / <old> / <new> / <flag> es la forma del comando sustituto, un paradigma que todavía se ve en muchos otros editores de texto (bueno, vim, un descendiente directo de ed) De todos modos, lag
bandera significa "global" y significa "Cada instancia en cada línea que miras". El rango3,5
mira las líneas 3-5.,5
mira StartOfFile-5,3,
mira las líneas 3-EndOfFile y,
mira StartOfFile-EndOfFile. Un comando de sustitución global en cada línea que reemplaza "falso" por "verdadero". Luego,w
se ingresa el comando de escritura,.Muy buenos ejemplos. Tuve el desafío de editar muchos archivos y la opción -i parece ser la única solución razonable al usarla dentro del comando find. Aquí el script para agregar "versión:" delante de la primera línea de cada archivo:
fuente