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 -iopción pero mi sistema Solaris dijo que -ies una opción ilegal. ¿Hay una manera diferente?
300

-ies 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
-iopció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
sedno 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-iopción espera unextensionargumento, por lo que su comando se analiza realmente como elextensionargumento y la ruta del archivo se interpreta como el código del comando. Fuente: https://stackoverflow.com/a/19457213fuente
brew install gnu-sedjunto con aPATHle 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
sedes 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>&nbuffers, sockets y similares). Con esto en mente, puede usar otro comandoteepara 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/stdinno existe, por lo que debe reemplazarlo/dev/stdincon '-', 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 - | patchpatchno se truncará también. Creo que guardar la salida en otro archivo y luegocatconvertirlo en original sería más seguro.No es posible hacer lo que quieres con
sed. Incluso las versionessedque admiten la-iopció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 defooabaren 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
-isoportesed, 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
inlinee invocaría como se describe arriba:inline inputfile sed 's/foo/bar/g'edsolo 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 evitartrllamadas adicionales .edrealmente no hace las modificaciones en el lugar. Desde lastracesalida, GNUedcrea un archivo temporal, escribe los cambios en el archivo temporal, luego reescribe todo el archivo original, conservando los enlaces duros. Desde latrusssalida, Solaris 11edtambién usa un archivo temporal, pero cambia el nombre del archivo temporal al nombre del archivo original al guardar con elwcomando, destruyendo los enlaces duros.edque 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.txtcon el texto:Si desea mantener una copia de seguridad del archivo anterior, use:
Terminarás con dos archivos:
hello.txtcon el contenido:y
hello.txt.bakcon 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 cuandocpfinaliza.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, lagbandera significa "global" y significa "Cada instancia en cada línea que miras". El rango3,5mira las líneas 3-5.,5mira 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,wse 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