bash 将输出从 sed 's/c/d/' myFile 重定向到 myFile
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2585438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Redirect output from sed 's/c/d/' myFile to myFile
提问by sixtyfootersdude
I am using sed in a script to do a replace and I want to have the replaced file overwrite the file. Normally I think that you would use this:
我在脚本中使用 sed 进行替换,我想让替换的文件覆盖该文件。通常我认为你会使用这个:
% sed -i 's/cat/dog/' manipulate
sed: illegal option -- i
However as you can see my sed does not have that command.
但是,正如您所看到的,我的 sed 没有该命令。
I tried this:
我试过这个:
% sed 's/cat/dog/' manipulate > manipulate
But this just turns manipulate into an empty file (makes sense).
但这只是将操纵变成了一个空文件(有道理)。
This works:
这有效:
% sed 's/cat/dog/' manipulate > tmp; mv tmp manipulate
But I was wondering if there was a standard way to redirect output into the same file that input was taken from.
但我想知道是否有一种标准的方法可以将输出重定向到与输入相同的文件中。
回答by Nathan Kidd
I commonly use the 3rd way, but with an important change:
我通常使用第三种方式,但有一个重要的变化:
$ sed 's/cat/dog/' manipulate > tmp && mv tmp manipulate
$ sed 's/cat/dog/' manipulate > tmp && mv tmp manipulate
I.e. change ;
to &&
so the move only happens if sed is successful; otherwise you'll lose your original file as soon as you make a typo in your sed syntax.
即更改;
为&&
因此移动仅在 sed 成功时发生;否则,只要您在 sed 语法中打错字,您就会丢失原始文件。
Note!For those reading the title and missing the OP's constraint "my sed doesn't support -i
": For most people, sed will support -i
, so the best way to do this is:
笔记!对于那些阅读标题并错过 OP 约束“我的 sed 不支持-i
”的人:对于大多数人来说, sed 将支持-i
,因此最好的方法是:
$ sed -i 's/cat/dog/' manipulate
$ sed -i 's/cat/dog/' manipulate
回答by gatt
Yes, -i
is also supported in FreeBSD/MacOSX sed
, but needs the empty string as an argument to edit a file in-place.
是的,-i
在 FreeBSD/MacOSX 中也受支持sed
,但需要空字符串作为参数来就地编辑文件。
sed -i "" 's/old/new/g' file # FreeBSD sed
回答by amertune
If you don't want to move copies around, you could use ed:
如果您不想移动副本,可以使用 ed:
ed file.txt <<EOF
%s/cat/dog/
wq
EOF
回答by Alok Singhal
Kernighan and Pike in The Art of Unix Programmingdiscuss this issue. Their solution is to write a script called overwrite
, which allows one to do such things.
Kernighan 和 Pike 在The Art of Unix Programming 中讨论了这个问题。他们的解决方案是编写一个名为 的脚本overwrite
,它允许人们做这样的事情。
The usage is: overwrite
file
cmd
file
.
用法是:。overwrite
file
cmd
file
# 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=; 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: failed, $file unchanged" 1>&2
exit 1
fi
rm -f $new $old
Once you have the above script in your $PATH
, you can do:
在您的 中有上述脚本后$PATH
,您可以执行以下操作:
overwrite manipulate sed 's/cat/dog/' manipulate
To make your life easier, you can use replace
script from the same book:
为了让您的生活更轻松,您可以使用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=""; right=""; shift; shift
for i
do
overwrite $i sed "s@$left@$right@g" $i
done
Having replace
in your $PATH
too will allow you to say:
拥有replace
你的$PATH
太将让你说:
replace cat dog manipulate
回答by nh2
回答by Stenemo
To change multiple files (and saving a backup of each as *.bak):
要更改多个文件(并将每个文件的备份保存为 *.bak):
perl -p -i -e "s/oldtext/newtext/g" *
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)
回答by falstro
Perhaps -i
is gnu sed, or just an old version of sed, but anyways. You're on the right track. The first option is probably the most common one, the third option is if you want it to work everywhere (including solaris machines)... :) These are the 'standard' ways of doing it.
也许-i
是 gnu sed,或者只是一个旧版本的 sed,但无论如何。你在正确的轨道上。第一个选项可能是最常见的选项,第三个选项是如果您希望它在任何地方都可以使用(包括solaris 机器)... :) 这些是执行此操作的“标准”方法。
回答by mouviciel
-i
option is not available in standard sed
.
-i
选项在标准中不可用sed
。
Your alternatives are your third way or perl
.
您的替代方案是您的第三种方式或perl
。
回答by Vladimir Prudnikov
A lot of answers, but none of them is correct. Here is the correct and simplest one:
很多答案,但没有一个是正确的。这是正确且最简单的一种:
$ echo "111 222 333" > file.txt
$ sed -i -s s/222/444/ file.txt
$ cat file.txt
111 444 333
$
回答by Jürgen H?tzel
Workaround using open file handles:
使用打开的文件句柄的解决方法:
exec 3<manipulate
Prevent open file from being truncated:
防止打开的文件被截断:
rm manipulate
sed 's/cat/dog/' <&3 > manipulate