と同等の機能が必要な場合はsed -i.bak
、非常に簡単です。
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"
マークした行を次のように簡単に置き換えることができます
cp "$dir/foo" "$dir/foo.bak" && sed -e "$script" "$dir/foo.bak" >"$dir/foo"
これにより、既存のファイルがバックアップとして移動され、新しいファイルが書き込まれます。
同等のものが必要な場合
sed -i -e "$script" "$dir" # no backup
その後、少し複雑になります。ファイルを開いて標準入力として読み込み、リンクを解除してから、sedの出力を置き換えて置き換えます。
( cp "$dir/foo" "$dir/foo.bak"; exec <"$dir/foo.bak"; rm "$dir/foo.bak"; exec sed -e "$script" >"$dir/foo" )
これはサブシェルで行うため、元のstdinはこの後も引き続き使用できます。入力を切り替えてサブシェルなしで元に戻すことは可能ですが、この方法は私にはより明確に思えます。
新しいfoo
ファイルを作成するのではなく、最初に注意してコピーすることに注意してください。これは、ファイルが複数の名前で知られている(つまり、ハードリンクがある)場合、リンクを壊さないようにしたい場合に重要です。 。
/usr/gnu/bin/sed
-iサポートを取得するために使用します。