bash - examples - sed linux reemplazar
Redirigir la salida de sed ''s/c/d/'' myFile a myFile (10)
Estoy usando sed en una secuencia de comandos para hacer un reemplazo y quiero que el archivo reemplazado sobrescriba el archivo. Normalmente creo que usarías esto:
% sed -i ''s/cat/dog/'' manipulate
sed: illegal option -- i
Sin embargo como puedes ver mi sed no tiene ese comando.
Intenté esto:
% sed ''s/cat/dog/'' manipulate > manipulate
Pero esto solo convierte la manipulación en un archivo vacío (tiene sentido).
Esto funciona:
% sed ''s/cat/dog/'' manipulate > tmp; mv tmp manipulate
Pero me preguntaba si había una forma estándar de redirigir la salida al mismo archivo del que se tomó la entrada.
Kernighan y Pike en la programación de The Art of Unix discuten este tema. Su solución es escribir un script llamado overwrite
, que permite hacer tales cosas.
El uso es: overwrite
file
cmd
.
# overwrite: copy standard input to output after EOF
opath=$PATH
PATH=/bin:/usr/bin
case $# in
0|1) echo ''Usage: overwrite file cmd [args]'' 1>&2; exit 2
esac
file=$1; shift
new=/tmp/overwr1.$$; old=/tmp/overwr2.$$
trap ''rm -f $new $old; exit 1'' 1 2 15 # clean up
if PATH=$opath "$@" >$new
then
cp $file $old # save original
trap '''' 1 2 15 # wr are commmitted
cp $new $file
else
echo "overwrite: $1 failed, $file unchanged" 1>&2
exit 1
fi
rm -f $new $old
Una vez que tenga el script anterior en su $PATH
, puede hacer:
overwrite manipulate sed ''s/cat/dog/'' manipulate
Para hacer su vida más fácil, puede usar replace
script del mismo libro:
# replace: replace str1 in files with str2 in place
PATH=/bin:/usr/bin
case $# in
0|2) echo ''Usage: replace str1 str2 files'' 1>&2; exit 1
esac
left="$1"; right="$2"; shift; shift
for i
do
overwrite $i sed "s@$left@$right@g" $i
done
Tener replace
en su $PATH
también le permitirá decir:
replace cat dog manipulate
Muchas respuestas, pero ninguna de ellas es correcta. Aquí está el correcto y el más simple:
$ echo "111 222 333" > file.txt
$ sed -i -s s/222/444/ file.txt
$ cat file.txt
111 444 333
$
Normalmente uso la tercera vía, pero con un cambio importante :
$ sed ''s/cat/dog/'' manipulate > tmp && mv tmp manipulate
Es decir cambio a &&
así que el movimiento solo sucede si sed tiene éxito; de lo contrario, perderá su archivo original tan pronto como cometa un error tipográfico en su sintaxis sed.
¡Nota! Para aquellos que leen el título y pierden la restricción del OP "my sed no admite -i
" : para la mayoría de las personas, sed admitirá -i
, por lo que la mejor manera de hacerlo es:
$ sed -i ''s/cat/dog/'' manipulate
Para cambiar varios archivos (y guardar una copia de seguridad de cada uno como * .bak):
perl -p -i -e "s / oldtext / newtext / g" *
replaces any occurence of oldtext by newtext in all files in the current folder. However you will have to escape all perl special characters within oldtext and newtext using the backslash
This is called a “Perl pie” (mnemonic: easy as a pie)
The -i flag tells it do do in-place replacement, and it should be ok to use single (“''”) as well as double (“””) quotes.
If using ./* instead of just *, you should be able to do it in all sub-directories
See man perlrun for more details, including how to take a backup file of the original.
using sed:
sed -i ''s/old/new/g'' ./* (used in GNU)
sed -i '''' ''s/old/new/g'' ./* (used in FreeBSD)
Puede utilizar sponge
de los moreutils .
sed "s/cat/dog/" manipulate | sponge manipulate
Quizás -i
sea gnu sed, o simplemente una versión antigua de sed, pero de todos modos. Estás en el camino correcto. La primera opción es probablemente la más común, la tercera opción es si desea que funcione en todas partes (incluidas las máquinas solaris) ... :) Estas son las formas "estándar" de hacerlo.
Sí, -i
también es compatible con FreeBSD / MacOSX sed
, pero necesita la cadena vacía como argumento para editar un archivo en el lugar.
sed -i "" ''s/old/new/g'' file # FreeBSD sed
Si no desea mover las copias, puede usar ed:
ed file.txt <<EOF
%s/cat/dog/
wq
EOF
Solución utilizando los manejadores de archivos abiertos:
exec 3<manipulate
Evita que el archivo abierto sea truncado:
rm manipulate
sed ''s/cat/dog/'' <&3 > manipulate
-i
opción -i
no está disponible en sed
estándar.
Tus alternativas son tu tercera vía o perl
.