Estoy tratando de averiguar si es posible editar un archivo en un solo comando sed sin manualmente streaming el contenido editado en un nuevo archivo y, a continuación, cambiar el nombre del nuevo archivo el nombre del archivo original. He probado el -i opción pero mi sistema Solaris dijo que -i es ilegal opción. Es allí una manera diferente?

  • -i es una opción en gnu sed, pero no está en el estándar de la sed. Sin embargo, los arroyos de contenido a un nuevo archivo y, a continuación, cambia el nombre del archivo, por lo que no es lo que quieres.
  • en realidad, es lo que yo quiero, sólo quiero no estar expuesto a tener que llevar a cabo la tarea rutinaria de cambiar el nombre del nuevo archivo con el nombre original
  • Entonces usted necesita para volver a formular la pregunta.
  • Le importaría en absoluto el prefijo de tu pregunta del título con la palabra ‘Solaris’? El valor de la pregunta que se está perdiendo. Por favor, consulte los comentarios de abajo de mi respuesta. Gracias.
  • He quitado el Solaris prefijo de nuevo el título, porque esto no es exclusivo de Solaris.
  • Seguro, pero creo que el título es ahora menos descriptivo. Tal vez: «sed edición en el lugar sin manualmente streaming el contenido editado en un archivo temporal y la realización de un cambio de nombre»? Demasiado tiempo?
  • No es, posiblemente, para satisfacer todas sus limitaciones. Usted podría utilizar ed en lugar de sed, o por streaming a través de un búfer de memoria utilizando sed "$f" | sponge "$f", o podría instalar GNU sed. Cual de los mejores direcciones de su situación particular está más allá de nuestro conocimiento (para una cosa, probablemente depende del tamaño del archivo que se está procesando).

InformationsquelleAutor amphibient | 2012-10-02

13 Comentarios

  1. 380

    La -i opción los arroyos de editar el contenido en un nuevo archivo y, a continuación, cambia el nombre de detrás de las escenas, de todos modos.

    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
    

    sobre macOS.

    • por lo menos no para mí, así que no tiene que
    • Usted podría tratar de compilar el GNU sed en su sistema, entonces.
    • ejemplo: sed -i "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
    • Esto es mejor que el perl de la solución. De alguna manera no crear ninguna .archivo de intercambio …. gracias!
    • Sí, pero tal vez en algún otro lugar o por un tiempo más corto?
    • +1 para «La opción-i los arroyos de editar el contenido en un nuevo archivo y, a continuación, cambia el nombre de detrás de las escenas»
    • en Yocto sistema de compilación siguiente ejemplo funciona: sed -i -e 's,STRING with SPACES,STRING to REPLACE with,g' filename – es decir, son importantes comas , en lugar de barras /
    • Alguna manera de hacer este trabajo de la cruz-plataforma con la misma sintaxis?
    • Crear un archivo tmp explícitamente, cambiar el nombre después.
    • Yo estaba teniendo problemas con Git en Windows pensando que el archivo entero había cambiado. Asegúrese de que si usted va esta ruta de comprobar los finales de línea.
    • Kokorin la respuesta anterior parece que funciona en Mac. I. e. uso sed -i -e 's/blah/blah/g'.

  2. 69

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

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

    Aunque esto crea un archivo temporal, que sustituye a la original debido a un vacío en el lugar sufijo/extensión ha sido suministrado.

    • No sólo crear un archivo temporal, también se rompe enlaces duros (por ejemplo, en lugar de cambiar el contenido del archivo, se reemplaza el archivo con un nuevo archivo con el mismo nombre.) A veces esto es el comportamiento deseado, a veces es aceptable, pero cuando hay varios enlaces a un archivo es casi siempre el mal comportamiento.
    • No todos los sistemas tienen un perl y aquí es donde la tubería entra en juego. Véase mi respuesta a continuación.
    • Creo que todos los sistemas sin Perl están rotos. Un solo comando triunfos de una cadena de comandos cuando uno quiere permisos elevados y deben utilizar sudo. En mi mente, la pregunta es acerca de cómo evitar la creación manual y cambiar el nombre de un archivo temporal sin tener que instalar la última GNU o BSD sed. Sólo el uso de Perl.
    • No es una respuesta a la pregunta original.
    • De verdad? Si usted lee la pregunta cuidadosamente, usted comprenderá que el OP está tratando de evitar algo como, sed 's/foo/bar/g' file.txt > file.tmp && mv file.tmp file.txt. Sólo porque en lugar de editar hace el cambio de nombre mediante un archivo temporal, no significa que él/ella debe realizar un manual de cambiar el nombre cuando la opción no está disponible. Hay otras herramientas que pueden hacer lo que él/ella quiere, y Perl es la opción obvia. ¿No es esto una respuesta a la pregunta original?
    • Votada abajo porque la respuesta es demasiado obstinado. OP preguntó cómo hacerlo con sed.
    • Tienes razón; él lo hizo. Pero él no puede lograr lo que quiere usando Solaris sed. La pregunta en realidad era muy buena, pero su valor se ha visto disminuida por la gente que no puede leer las páginas man o no puede ser molestado en la verdad leer las preguntas aquí sobre ESO.
    • «y Perl es la opción obvia» … <tos> – yo, respetuosamente sugerimos Perl ya no es la opción obvia (aunque alguna vez lo fue). Perl ha sido obviado por Python y Ruby, de la OMI. Mientras estamos en ello, el OP quería un sed solución.
    • Si mal no recuerdo, Solaris barcos con Perl, pero no de Python o Ruby. Y como he dicho antes, el OP no se puede lograr el resultado deseado usando Solaris sed.
    • gracias por el aviso, me perdí el Solaris requisito.

  3. 50

    Tenga en cuenta que en OS X, se puede obtener errores extraños como «no válido código de comando» u otras extrañas errores cuando se ejecuta este comando. Para solucionar este problema intente

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

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

    • Esta es otra rareza de OS X. Afortunadamente, un brew install gnu-sed junto con un PATH permitirá el uso de la versión GNU de sed. Gracias por mencionar; en definitiva un rascador de cabeza.
  4. 23

    La siguiente funciona bien en mi mac

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

    Estamos sustituyendo foo con barra de en archivo de muestra. Copia de seguridad del archivo original se guardará en la muestra.bak

    Para la edición en línea sin copia de seguridad, utilice el siguiente comando

    sed -i'' 's/foo/bar/g' sample
    
    • Cualquier forma de cómo evitar que se mantenga archivos de copia de seguridad?
    • Puede utilizar el comando mencionado por el mismo… sed-i » ‘s/foo/bar/g’ de la muestra
  5. 13

    Una cosa a tener en cuenta, sed no puede escribir archivos en su propio como el único propósito de sed es la de actuar como un editor en el «stream» (es decir, las tuberías de stdin, stdout, stderr, y otros >&n buffers, sockets y similares). Con esto en mente usted puede usar otro comando tee para escribir el resultado en el archivo. Otra opción es crear un parche de la tubería el contenido en diff.

    Tee método


    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 el parche va a conseguir el archivo para cambiar de la línea 1 de la salida diff:

    Parche no necesita saber qué archivo de acceso ya que este 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
    
    • /dev/stdin 2014-03-15, respondió Jan 7 – eres un viajero del tiempo?
    • En Windows, el uso de msysgit, /dev/stdin no existe, por lo que tiene que reemplazar a /dev/stdin con ‘-‘, un único guión sin las comillas, por lo que los siguientes comandos deben trabajar: $ sed 's/oo/u/' fubar | diff -p fubar - y $ sed 's/oo/u/' fubar | diff -p fubar - | patch
    • Yo tengo una azul caja de policía en algún lugar alrededor y, por alguna razón, ellos me llaman el Médico en el trabajo. Pero, sinceramente, parece que no hay realmente malo reloj a la deriva en el sistema en el tiempo.
    • Estas soluciones se parecen a mí confiar en particular el búfer de comportamiento. Sospecho que para archivos más grandes, estos pueden romper como mientras que la sed es la lectura, el archivo puede empezar a cambiar por debajo por el comando patch, o peor aún por el tee de comandos que se trunca el archivo. En realidad no estoy seguro si patch no truncar así. Creo que el ahorro de salida a otro archivo y, a continuación, cat– ing en el original sería más seguro.
    • real en lugar de la respuesta de @william-pursell
    • Tenga en cuenta que en BSD, -yo también cambia el comportamiento cuando hay varios archivos de entrada: son procesados de forma independiente (por ejemplo, $ coincide con la última línea de cada archivo). También el directamente bandera no funciona en BusyBox y Solaris, ni la fiabilidad bajo MacRelix/Cygwin. Más directamente sed en sí, se basa en el búfer de comportamiento. En todos los casos no hay ningún archivo de bloqueo por lo que los archivos pueden ser cambiados antes de la sed, diff/parche o alguna de las herramientas estándar de unix resolver y escribir en el archivo. Si uno es que se trate, a continuación, uno sólo debe utilizar un fifo. Como para el parche no truncar los archivos.

  6. 10

    No es posible hacer lo que quieran con sed. Incluso las versiones de sed que apoyan la -i opción para la edición de un archivo en lugar de hacer exactamente lo que te han dicho explícitamente que no quieren escribir en un archivo temporal y, a continuación, cambie el nombre del archivo. Pero tal vez usted puede utilizar ed. Por ejemplo, para cambiar todas las apariciones de foo a bar en el archivo file.txt, usted puede hacer:

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

    Sintaxis es similar a la sed, pero ciertamente no es exactamente el mismo.

    Pero tal vez usted debería considerar la posibilidad de por qué usted no desea utilizar se ha cambiado el nombre de archivo temporal. Incluso si usted no tiene un -i apoyo sed, fácilmente puede escribir un script para hacer el trabajo para usted. En lugar de sed -i 's/foo/bar/g' file, usted podría hacer inline file sed 's/foo/bar/g'. Este script es trivial para escribir. Por ejemplo:

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

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

    • así, por ejemplo, ¿cómo sería su nombre de este script y cómo lo llaman?
    • Yo diría que es inline y llámalo como se describe anteriormente: inline inputfile sed 's/foo/bar/g'
    • wow, ed única respuesta que realmente en el lugar. La primera vez que la necesidad ed. Gracias. Un poco de optimización es el uso de echo -e ",s/foo/bar/g\012 w" o echo $',s/foo/bar/g\012 w' donde shell le permite evitar el exceso de tr llamada.
    • ed realmente no hacer las modificaciones en el lugar. De strace de salida, GNU ed crea un archivo temporal, escribe los cambios en el archivo temporal, vuelve a escribir todo el archivo original, la preservación de los enlaces duros. De truss de salida, Solaris 11 ed también utiliza un archivo temporal, pero cambia el nombre del archivo temporal para el original nombre de archivo al guardar con el w comando, la destrucción de los enlaces duros.
  7. 7

    sed admite la edición en el lugar. De man sed:

    -i[SUFFIX], --in-place[=SUFFIX]
    
        edit files in place (makes backup if extension supplied)
    

    Ejemplo:

    Digamos que usted tiene un archivo hello.txtcon el texto:

    hello world!
    

    Si desea mantener una copia de seguridad del archivo antiguo, uso:

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

    Usted va a terminar con dos archivos: hello.txt con el contenido de:

    bonjour world!
    

    y hello.txt.bak con el contenido antiguo.

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

    • El OP menciona específicamente que su plataforma no es compatible con esta popular (pero) no estándar de la opción.
  8. 3
    mv file.txt file.tmp && sed 's/foo/bar/g' < file.tmp > file.txt
    

    Debe conservar todos los enlaces permanentes, ya que la salida se dirige de nuevo a sobrescribir el contenido del archivo original, y evita la necesidad de una versión especial de sed.

  9. 3

    Si va a sustituir la misma cantidad de caracteres y después de leer cuidadosamente «En lugar de» edición de archivos

    También puede utilizar el operador de redirección <> abrir el archivo para lectura y escritura:

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

    Ver 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 Manual de Referencia → 3.6.10 la 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 la palabra que se abrirán para
    tanto la lectura y la escritura en el archivo descriptor de n, o en el archivo descriptor 0
    si no se especifica n. Si el archivo no existe, se crea.

    • Esta dañado el archivo. No estoy seguro de la razón detrás de ella. paste.fedoraproject.org/462017
    • Ver líneas de [43-44], [88-89], [135-136]
    • Esta publicación de blog explica por qué esta respuesta no debe ser utilizado. backreference.org/2011/01/29/in-place-editing-of-files
    • Voy a tener un tiempo de leer el artículo, gracias por el heads-up! Lo que no se menciona en la respuesta es que esto funciona si se cambia la misma cantidad de caracteres.
    • dicho esto, lo siento si mi respuesta daños causados en sus archivos. Voy a actualizar con correcciones (o eliminar si es necesario) después de leer los enlaces que proporcionan.
    • actualizado con una advertencia en la parte superior. Gracias por el enlace a esta muy completo el artículo.

  10. 2

    No especificar lo que shell está utilizando, pero con zsh podría utilizar el =( ) construir 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.

    • lo siento, estoy usando ksh
  11. 1

    Muy buenos ejemplos. Yo tenía el reto de editar en lugar de muchos archivos y la opción-i parece ser la única solución razonable de usarlo en el comando buscar. Aquí la secuencia de comandos para agregar «versión:» en frente de la primera línea de cada archivo:

    find . -name pkg.json -print -exec sed -i '.bak' '1 s/^/version /' {} \;
    
  12. 1

    Como Moneypenny dijo en Skyfall: «a Veces las viejas formas son las mejores.»
    Kincade dijo algo similar más adelante.

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

    Feliz de edición en el lugar.
    Añadido ‘\nw\n’ para escribir el archivo. Disculpas por el retraso respuesta a la solicitud.

    • ¿Puede explicar por qué este no?
    • Se invoca ed(1), el editor de texto con algunos caracteres escritos a stdin. Como alguien bajo la edad de 30, creo que es bueno para mí decir que ed(1) es el mundo de los dinosaurios los dinosaurios son para nosotros. De todos modos, en lugar de la apertura de ed y escribir que cosas, jlettvin es la canalización de los personajes en el uso de |. @MattMontag
    • Si usted se está preguntando lo que el manda hacer, hay dos de ellos, terminado por un \n. [rango]s/<viejo>/<nuevo>/<bandera> es la forma de que el sustituto de comandos de un paradigma aún se ve en muchos otros editores de texto (bueno, vim, un descendiente directo de ed) de todos Modos, el g bandera que representa «global», y significa «Cada instancia, en cada línea que se mira». La gama 3,5 se ve en las líneas 3 a 5. ,5 mira StartOfFile-5, 3, se ve en las líneas 3-EndOfFile y , mira StartOfFile-EndOfFile. Un mundial substitue comando en cada línea que sustituye a «false» por «true». A continuación, el comando de escritura, w, es introducido.

Dejar respuesta

Please enter your comment!
Please enter your name here