我想在OS x上用sed编辑一个文件,我正在使用以下命令:
sed 's/oldword/newword/' file.txt
输出结果被发送到终端。File.txt未被修改。使用下面的命令将更改保存到file2.txt:
sed 's/oldword/newword/' file1.txt > file2.txt
但是我不想要另一个文件。我只想编辑file1.txt。我该怎么做呢?
我尝试了-i标志。这将导致以下错误:
sed: 1: "file1.txt": invalid command code f
-i标志可能不适合您,因为您使用的是GNU sed的示例,而macOS使用的是BSD sed,它们的语法略有不同。
所有其他答案都告诉您如何纠正语法以使用BSD sed。另一种选择是在你的macOS上安装GNU sed:
brew install gsed
然后使用它来代替macOS附带的sed版本(注意g前缀),例如:
gsed -i 's/oldword/newword/' file1.txt
如果你想要GNU sed命令总是可以移植到macOS,你可以在你的路径前加上“gnubin”目录,通过在你的.bashrc/中添加这样的东西。ZSHRC文件(运行brew info gsed看看你到底需要做什么):
export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
从那时起,GNU sed就变成了默认sed,你可以简单地运行:
sed -i 's/oldword/newword/' file1.txt
-i标志可能不适合您,因为您使用的是GNU sed的示例,而macOS使用的是BSD sed,它们的语法略有不同。
所有其他答案都告诉您如何纠正语法以使用BSD sed。另一种选择是在你的macOS上安装GNU sed:
brew install gsed
然后使用它来代替macOS附带的sed版本(注意g前缀),例如:
gsed -i 's/oldword/newword/' file1.txt
如果你想要GNU sed命令总是可以移植到macOS,你可以在你的路径前加上“gnubin”目录,通过在你的.bashrc/中添加这样的东西。ZSHRC文件(运行brew info gsed看看你到底需要做什么):
export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
从那时起,GNU sed就变成了默认sed,你可以简单地运行:
sed -i 's/oldword/newword/' file1.txt
您可以像前面建议的那样,对sed使用-i”(——in-place)。参见:-i in-place参数,但请注意-i选项是非标准FreeBSD扩展,可能在其他操作系统上不可用。其次,sed是一个流编辑器,而不是文件编辑器。
另一种方法是在Vim Ex模式中使用内置替换,例如:
$ ex +%s/foo/bar/g -scwq file.txt
对于多个文件:
$ ex +'bufdo!%s/foo/bar/g' -scxa *.*
要递归地编辑所有文件,可以使用**/*。*如果shell支持(通过shop -s globstar启用)。
另一种方法是使用gawk和它新的“inplace”扩展,例如:
$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1
您可以通过向-i标志提供要添加到备份文件的后缀来正确使用-i标志。扩展你的例子:
sed -i.bu 's/oldword/newword/' file1.txt
将给您两个文件:一个文件名为file1.txt,其中包含替换,另一个文件名为file1.txt。但那是原创的内容。
温和的危险
如果你想要破坏性地覆盖原始文件,可以使用如下方法:
sed -i '' 's/oldword/newword/' file1.txt
^ note the space
由于行解析的方式,选项标志和它的参数之间需要一个空格,因为参数是零长度。
除了可能毁掉你的原作,我不知道用这种方式欺骗sed会有什么进一步的危险。但是,应该注意的是,如果sed的调用是脚本的一部分,那么Unix Way™(IMHO)将是非破坏性地使用sed,测试它是否干净地退出,然后才删除无关的文件。