如果您想要等效于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支持。