在OS X上使用sed进行就地编辑

Sun*_*day 130 macos file-io sed in-place

我想在OS X上使用sed编辑文件.我正在使用以下命令:

sed 's/oldword/newword/' file.txt
Run Code Online (Sandbox Code Playgroud)

输出发送到终端. file.txt未被修改.使用以下命令将更改保存到file2.txt:

sed 's/oldword/newword/' file1.txt > file2.txt
Run Code Online (Sandbox Code Playgroud)

但是我不想要另一个文件.我只想编辑file1.txt.我怎样才能做到这一点?

我试过-i标志.这会导致以下错误:

sed: 1: "file1.txt": invalid command code f
Run Code Online (Sandbox Code Playgroud)

小智 251

通过为其提供后缀以添加到备份文件,可以正确使用-i标志.扩展你的例子:

sed -i.bu 's/oldword/newword/' file1.txt
Run Code Online (Sandbox Code Playgroud)

将为您提供两个文件:一个文件名为file1.txt,其中包含替换文件,另一个文件名为file1.txt.bu,其中包含原始内容.

轻度危险

如果要破坏性地覆盖原始文件,请使用以下内容:

sed -i '' 's/oldword/newword/' file1.txt
      ^ note the space
Run Code Online (Sandbox Code Playgroud)

由于行解析的方式,选项标志和其参数之间需要一个空格,因为参数是零长度.

除了可能捣毁你的原件之外,我不知道以这种方式欺骗sed还有任何进一步的危险.然而,应该注意的是,如果这个调用-i是脚本的一部分,那么Unix Way™(IMHO)将file1.txt非破坏性地使用,测试它是否干净地退出,然后才删除无关的文件.

  • BSD sed要求-i标志后没有空格.所以,`-i''`是有效的,但`-i''`不是. (3认同)
  • 哎呀!BSD sed忽略'\n'字符并打印'n'代替!我只想用我的mac上的GNU sed替换BSD sed! (3认同)
  • 我发现轻度危险的位特别有用。+1 (2认同)

小智 17

我和MacOS有类似的问题

sed -i '' 's/oldword/newword/' file1.txt
Run Code Online (Sandbox Code Playgroud)

不起作用,但是

sed -i"any_symbol" 's/oldword/newword/' file1.txt
Run Code Online (Sandbox Code Playgroud)

效果很好.

  • 现在情况正好相反。`sed -i '' <file>` 有效,但 `sed -i'' <file>` 不再有效 (6认同)

小智 9

sed -i -- "s/https/http/g" file.txt
Run Code Online (Sandbox Code Playgroud)

  • 在我的 macOS (10.15.6) 上,`--` 似乎可以工作,但实际上它会创建一个 `file.txt--` 备份文件,然后必须手动删除该文件,因此这个解决方案并不比接受的解决方案更好一。并且“--”具有误导性,就好像该选项的作用就像 GNU 工具一样,以不同的方式对待它。 (4认同)

Jak*_*kul 8

-i标志可能对您不起作用,因为您遵循了GNU sed的示例,而 macOS 使用BSD sed并且它们的语法略有不同。

所有其他答案都告诉您如何更正语法以使用 BSD sed。另一种方法是在你的 macOS 上安装 GNU sed:

brew install gsed
Run Code Online (Sandbox Code Playgroud)

然后使用它而不是sedmacOS 附带的版本(注意g前缀),例如:

gsed -i 's/oldword/newword/' file1.txt
Run Code Online (Sandbox Code Playgroud)

如果您希望 GNU sed 命令始终可移植到您的 macOS,您可以将“gnubin”目录添加到您的路径中,方法是在您的.bashrc/.zshrc文件中添加类似的内容(运行brew info gsed以查看您需要做什么):

export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Run Code Online (Sandbox Code Playgroud)

从那时起,GNU sed 将成为您的默认 sed,您只需运行:

sed -i 's/oldword/newword/' file1.txt
Run Code Online (Sandbox Code Playgroud)


ken*_*orb 5

您可以按照已经建议的方式使用-i''( --in-place) sed。见:-i就地说法,但是请注意,-i选项是非标准的FreeBSD扩展和可能并不适用于其他操作系统。其次sed小号tream ED itor,而不是一个文件编辑器


另一种方法是在 Vim Ex 模式下使用内置替换,例如:

$ ex +%s/foo/bar/g -scwq file.txt
Run Code Online (Sandbox Code Playgroud)

对于多个文件:

$ ex +'bufdo!%s/foo/bar/g' -scxa *.*
Run Code Online (Sandbox Code Playgroud)

要以递归方式编辑所有文件,您可以使用**/*.*如果 shell 支持(通过 启用shopt -s globstar)。


另一种方法是使用gawk它的新“就地”扩展,例如:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1
Run Code Online (Sandbox Code Playgroud)