为什么带有多个“-e”的“sed”在 macOS Monterey 上最终会出错?

为什么带有多个“-e”的“sed”在 macOS Monterey 上最终会出错?

在 macOS Monterey 上,为什么会这样:

$ sed -i -e 's/<azure\/core\/internal\//</g' -e 's/<azure\/core\//</g' -e 's/<azure\/iot\/internal\//</g' -e 's/<azure\/iot\//</g' .

…最终出现以下错误:

sed: -e: No such file or directory

答案1

正如评论中提到的,BSD 版本的 sed-i采用强制参数,因此在 中sed -i -e-e成为该参数,用于备份文件的文件名后缀。然后,命令中的下一个参数是s/<azure\/core\/internal\//</g,并且因为没有看到-e或选项-f,这就是 sed 脚本。 (这与grep pattern file...和的工作方式相似grep -e pattern file...,并且执行相同的操作。)

标准行为是选项必须显示为第一个命令行参数。因此,在第一个非选项之后,其余的不会被解释为选项,即使它们以破折号开头。因此sed将它们作为文件名,以-e.

这在 GNU 上也有所不同,其中 egls dir -lls -l dir.但它不是标准的,Mac 上的 BSD sed 也不支持它。在 GNU 上,sed foo -e bar将识别-e为一个选项,bar作为 sed 脚本和foo文件名。但按照标准解释,foo将是脚本、-e-bar文件名。


用 解决问题-i,剩下的就水到渠成了。要在 Mac 上使用-i没有备份文件的选项,请使用

sed -i '' -e something -e something file...

请注意,这sed -i.bak可以与任一版本的 sed 一起使用,将备份后缀设置为.bak. (但sed -i .bak不会)

答案2

好的,这是我的解决方案:

sed -i '' -e 's/<azure\/core\/internal\//<azure-sdk-for-c\//g;s/<azure\/core\//<azure-sdk-for-c\//g;s/<azure\/iot\/internal\//<azure-sdk-for-c\//g;s/<azure\/iot\//<azure-sdk-for-c\//g' ./azure-sdk-for-c/*

相关内容