我在脚本中使用sed进行替换,我想让替换的文件覆盖该文件。通常我认为你会用这个:
% sed -i 's/cat/dog/' manipulate
sed: illegal option -- i
但是你可以看到我的sed没有那个命令。
我试过了:
% sed 's/cat/dog/' manipulate > manipulate
但这只是将操作转换为空文件(有意义)。
这有效:
% sed 's/cat/dog/' manipulate > tmp; mv tmp manipulate
但我想知道是否有一种标准方法可以将输出重定向到输入的同一文件中。
答案 0 :(得分:37)
我通常使用第三种方式,但重要更改:
$ sed 's/cat/dog/' manipulate > tmp && mv tmp manipulate
即。将;
更改为&&
,这样只有在sed成功时才会移动;一旦你用sed语法输入拼写错误,你就会丢失原始文件。
注意!对于那些阅读标题但缺少OP约束的人“我的sed不支持-i
”:对于大多数人来说,sed会支持-i
,所以最好的方法是:
$ sed -i 's/cat/dog/' manipulate
答案 1 :(得分:8)
是的,FreeBSD / MacOSX -i
也支持sed
,但需要空字符串作为参数来就地编辑文件。
sed -i "" 's/old/new/g' file # FreeBSD sed
答案 2 :(得分:6)
如果您不想移动副本,可以使用ed:
ed file.txt <<EOF
%s/cat/dog/
wq
EOF
答案 3 :(得分:3)
overwrite
的脚本,允许人们做这样的事情。
用法为:overwrite
file
cmd
file
。< / p>
# 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
在$PATH
中有上述脚本后,即可:
overwrite manipulate sed 's/cat/dog/' manipulate
为了让您的生活更轻松,您可以使用同一本书中的replace
脚本:
# 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
replace
中{{}}}也允许你说:
$PATH
答案 4 :(得分:2)
您可以使用moreutils中的sponge
。
sed "s/cat/dog/" manipulate | sponge manipulate
答案 5 :(得分:1)
也许-i
是gnu sed,或者只是旧版本的sed,但无论如何。你走在正确的轨道上。第一个选项可能是最常见的选项,第三个选项是如果你想让它在任何地方工作(包括solaris机器)...... :)这些都是“标准”的方法。
答案 6 :(得分:1)
要更改多个文件(并将每个文件的备份保存为* .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)
答案 7 :(得分:0)
-i
中没有 sed
选项。
您的替代方案是您的第三种方式或perl
。
答案 8 :(得分:0)
很多答案,但没有一个是正确的。这是最正确和最简单的一个:
$ echo "111 222 333" > file.txt
$ sed -i -s s/222/444/ file.txt
$ cat file.txt
111 444 333
$
答案 9 :(得分:-2)
使用打开文件句柄的解决方法:
exec 3<manipulate
阻止打开文件被截断:
rm manipulate
sed 's/cat/dog/' <&3 > manipulate