Se você quer o equivalente sed -i.bak
, é bem simples.
Considere este script para o 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"
Podemos simplesmente substituir a linha marcada por
cp "$dir/foo" "$dir/foo.bak" && sed -e "$script" "$dir/foo.bak" >"$dir/foo"
Isso move o arquivo existente para um backup e grava um novo arquivo.
Se queremos o equivalente a
sed -i -e "$script" "$dir" # no backup
então é um pouco mais complexo. Podemos abrir o arquivo para leitura como entrada padrão e desvinculá-lo antes de direcionar a saída do sed para substituí-lo:
( cp "$dir/foo" "$dir/foo.bak"; exec <"$dir/foo.bak"; rm "$dir/foo.bak"; exec sed -e "$script" >"$dir/foo" )
Fazemos isso em um sub-shell, para que nosso stdin original ainda esteja disponível depois disso. É possível alternar entradas e retornar sem um subshell, mas dessa maneira me parece mais claro.
Observe que temos o cuidado de copiar primeiro, em vez de criar um novo foo
arquivo - isso é importante se o arquivo for conhecido por mais de um nome (por exemplo, possui links físicos) e você quiser ter certeza de que não os quebrará. .
/usr/gnu/bin/sed
para obter o suporte -i.