Usando sedy novisiblearchivo temporal:

Usando sedy novisiblearchivo temporal:

Tengo el requisito en mi proyecto de reemplazar algún texto existente en un archivo comofoocon algún otro texto comofooofoo:

abc.txt
name
foo
foo1

Entonces lo intenté:

sed -i "s/foo/fooofoo/g" abc.txt

Sin embargo me sale este error:

sed: opción ilegal -i

Encontré en el manual que tengo que usar:

sed -i\ "s/foo/fooofoo/g" abc.txt

Sin embargo, esto tampoco funciona.

Encontré alternativas en perly también, pero agradecería mucho awkuna solución en Solaris .sed

Estoy usando esta versión de bash:

GNU bash, versión 3.2.57(1) (sparc-sun-solaris2.10)

Respuesta1

Usared. Está disponible en la mayoría de las plataformas y puede editar sus archivos en el lugar.
Dado que sedse basa en edla sintaxis para reemplazar patrones es similar:

ed -s infile <<\IN
,s/old/new/g
w
q
IN

Respuesta2

Si no puede instalar GNU sed, utilice:

sed "s/foo/fooofoo/g" abc.txt >abc.tmp && mv abc.tmp abc.txt

Esto usaredirecciónpara enviar la salida de sed a un archivo temporal. Si sed se completa correctamente, se sobrescribe abc.txtcon el archivo temporal.

Como se puede ver en el código fuente de GNU sed, esto es exactamente lo que sed -ihace. Entonces, esto es casi tan eficiente como sed -i.

Si existe la posibilidad de que abc.tmpya exista, es posible que desee utilizar mktempuna utilidad similar para generar el nombre único para el temporal.

Respuesta3

Si quieres el equivalente a sed -i.bak, es bastante simple.

Considere este script para GNU sed:

#!/bin/sh

# Create an input file to demonstrate
trap 'rm -r "$dir"' EXIT
dir=$(mktemp -d)
grep -v '[[:upper:][:punct:]]' /usr/share/dict/words | head >"$dir/foo"

# sed program - removes 'aardvark' and 'aardvarks'
script='/aard/d'

##########
# What we want to do
sed -i.bak -e "$script" "$dir"
##########

# Prove that it worked
ls "$dir"
cat "$dir/foo"

Simplemente podemos reemplazar la línea marcada con

cp "$dir/foo" "$dir/foo.bak" && sed -e "$script" "$dir/foo.bak" >"$dir/foo"

Esto mueve el archivo existente para que sea una copia de seguridad y escribe un archivo nuevo.

Si queremos el equivalente de

sed -i -e "$script" "$dir"  # no backup

entonces es un poco más complejo. Podemos abrir el archivo para leerlo como entrada estándar, luego desvincularlo, antes de dirigir la salida de sed para reemplazarlo:

( cp "$dir/foo" "$dir/foo.bak"; exec <"$dir/foo.bak"; rm "$dir/foo.bak"; exec sed -e "$script" >"$dir/foo" )

Hacemos esto en un sub-shell, para que nuestra entrada estándar original todavía esté disponible después de esto. Es posible cambiar las entradas y volver a cambiar sin una subcapa, pero de esta manera me parece más clara.

Tenga en cuenta que tenemos cuidado de copiar primero, en lugar de crear un fooarchivo nuevo; esto es importante si el archivo se conoce por más de un nombre (es decir, tiene enlaces físicos) y desea asegurarse de no romper los enlaces. .

Respuesta4

Usando sedy novisiblearchivo temporal:

Puedes evitar crear un separadovisible"archivo temporal":

exec 3<abc.txt
rm abc.txt
sed 's/foo/fooofoo/' <&3 >abc.txt
exec 3<&-

Explicación

Los sistemas tipo Unix en realidad no eliminan el contenido del archivo del disco hasta que seambosdesvinculado en el sistema de archivos,yno abierto en ningún proceso. Por lo tanto, puede exec 3<abrir el archivo en el shell para leer el descriptor de archivo 3, rmel archivo (que lo desvincula del sistema de archivos) y luego llamar sedcon el descriptor de archivo 3 utilizado como entrada.

Tenga en cuenta que esto esmuydiferente a esto:

# Does not work.
sed 's/foo/fooofoo/' <abc.txt >abc.txt

La diferencia es que cuando lo hace con un solo comando, el shell simplemente abre el mismo archivo para lectura y escritura con la opción de truncar el archivo; como sigue siendo el mismo archivo, pierde el contenido. Pero si lo abre para leer, rmluego abre el mismo nombre de ruta para escribir, en realidad está creando un nuevo archivo con el mismo nombre de ruta (pero en un nuevo inodo y ubicación de disco, ya que el original todavía está abierto): entonces Los contenidos aún están disponibles.

Luego, una vez que haya terminado, puede cerrar el descriptor de archivo que abrió anteriormente (eso es lo que exec 3<&-hace la sintaxis especial), lo que libera el archivo original para que el sistema operativo pueda eliminar (marcar como no utilizado) su espacio en disco.

Advertencias

Hay algunas cosas a tener en cuenta acerca de esta solución:

  1. Sólo puedes revisar el contenido una vez; no hayportátilmanera para que un shell "busque" nuevamente en el descriptor de archivo, por lo que una vez que un programa lee parte del contenido, otros programas solo verán el resto del archivo. Y sedleerá el archivo completo.

  2. Existe una pequeña posibilidad de que su archivo original se pierda si su shell/script/sed se elimina antes de finalizar.

información relacionada