我想在 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
标志时,您使用的确切命令是什么?
您可以正确使用 -i
标志,方法是为其提供一个后缀以添加到备份文件中。扩展您的示例:
sed -i.bu 's/oldword/newword/' file1.txt
将为您提供两个文件:一个名称为 file1.txt
包含替换,另一个名称为 file1.txt.bu
包含原始内容。
轻度危险
如果您想破坏性地覆盖原始文件,请使用以下内容:
sed -i '' 's/oldword/newword/' file1.txt
^ note the space
由于解析行的方式,选项标志和它的参数之间需要一个空格,因为参数是零长度的。
除了可能破坏您的原件外,我不知道以这种方式欺骗 sed 有任何进一步的危险。然而,应该注意的是,如果 sed
的调用是脚本的一部分,那么 Unix Way™ 将(恕我直言)非破坏性地使用 sed
,测试它是否干净地退出,然后才删除无关文件。
我对 MacOS 有类似的问题
sed -i '' 's/oldword/newword/' file1.txt
不起作用,但是
sed -i"any_symbol" 's/oldword/newword/' file1.txt
效果很好。
sed -i '' <file>
有效,但 sed -i'' <file>
不再有效
-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 -- "s/https/http/g" file.txt
--
似乎可以工作,但实际上它会创建一个 file.txt--
备份文件,然后必须手动删除该文件,因此此解决方案并不比公认的解决方案更好。并且 --
具有误导性,就好像该选项的行为就像 GNU 工具一样,以不同的方式对待它。
您可以按照前面的建议将 -i''
(--in-place
) 用于 sed
。请参阅:The -i
in-place argument,但请注意,-i
选项是非标准 FreeBSD 扩展,可能在其他操作系统上不可用。其次sed
is a Stream EDitor, not a file editor。
另一种方法是在 Vim Ex 模式下使用内置替换,例如:
$ ex +%s/foo/bar/g -scwq file.txt
对于多个文件:
$ ex +'bufdo!%s/foo/bar/g' -scxa *.*
要递归编辑所有文件,如果 shell 支持,您可以使用 **/*.*
(由 shopt -s globstar
启用)。
另一种方法是使用 gawk
及其新的 "inplace" extension,例如:
$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1
这将创建备份文件。例如 sed -i -e 's/hello/hello world/' testfile
对我来说,在同一个目录中创建一个备份文件 testfile-e。
您可以使用:
sed -i -e 's/<string-to-find>/<string-to-replace>/' <your-file-path>
例子:
sed -i -e 's/Hello/Bye/' file.txt
这在 Mac 中完美无缺。
-i
需要 macOS 的参数。由于您没有指定一个,因此它使用 -e
,这会导致第二个文件附加了 -e
。 -e
在 macOS 中不存在,它是 -E
。所以 macOS 的正确命令是 sed -i '' -E 's/Hello/Bye/' file.txt
不定期副业成功案例分享
-i''
是否有危险?sed
手册页,如果设备上的磁盘空间不足,您可能会在中途损坏文件并产生错误的输出结果。如果您在本地源代码控制下工作,则sed -i ""
没有备份大部分时间应该没问题(或者只是在-i
模式下运行 sed 之前的git init && git add -A . && git commit -m 'backup'
)。-i''
有效,但-i ''
无效。