Si vous voulez l'équivalent de sed -i.bak
, c'est assez simple.
Considérez ce script pour 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"
Nous pouvons simplement remplacer la ligne marquée par
cp "$dir/foo" "$dir/foo.bak" && sed -e "$script" "$dir/foo.bak" >"$dir/foo"
Cela déplace le fichier existant pour être une sauvegarde et écrit un nouveau fichier.
Si nous voulons l'équivalent de
sed -i -e "$script" "$dir" # no backup
alors c'est un peu plus complexe. Nous pouvons ouvrir le fichier pour le lire comme entrée standard, puis le dissocier, avant de diriger la sortie de sed pour le remplacer:
( cp "$dir/foo" "$dir/foo.bak"; exec <"$dir/foo.bak"; rm "$dir/foo.bak"; exec sed -e "$script" >"$dir/foo" )
Nous le faisons dans un sous-shell, afin que notre stdin d'origine soit toujours disponible après cela. Il est possible de changer d'entrée et de revenir en arrière sans sous-coque, mais cette façon me semble plus claire.
Notez que nous prenons soin de copier d'abord, plutôt que de créer un nouveau foo
fichier - cela est important si le fichier est connu sous plusieurs noms (c'est-à-dire avec des liens durs) et que vous voulez être sûr de ne pas rompre les liens .
/usr/gnu/bin/sed
support -i.