将“sed”与“-i”选项一起使用会创建名称奇怪的新文件,同时保持输入文件不变

将“sed”与“-i”选项一起使用会创建名称奇怪的新文件,同时保持输入文件不变

我有这个命令:

sed -i 's/^CREATE DATABASE.*$//' world.sql

如果我运行它,它会说:

sed: -I or -i may not be used with stdin

并创建一个名为 的新文件orld.sql。之后原始文件仍然存在。

所以我想,sed看到world.sql是一个 w orld.sql命令吗?我怎样才能防止这种行为?

[这是在 macOS 上。]

答案1

据我所知,sedMacOS 上有 FreeBSD 版本,需要使用该选项时要提供的备份后缀-i。您收到的错误消息意味着它错误地解释了命令的部分内容,因为您使用了该选项而没有提供选项。

所以,尝试一下

sed -i".backup" 's/^CREATE DATABASE.*$//' world.sql

这将创建world.sql.backup并以其他方式执行 的就地编辑world.sql

一些 sed版本可能接受空备份后缀,如sed -i '',这将阻止创建备份文件,但您需要在文档中查找您正在使用的特定版本。看

以获得更多见解

答案2

我们需要深入了解您的命令行的含义sed

sed -i 's/^CREATE DATABASE.*$//' world.sql

macOS sed 调用的语法是:

sed-i'后缀''命令'文件名

该选项的后缀是必需的-i。如果后缀为空,则-i与后缀之间必须至少有一个空格,如-i ''.这是针对 macOS sed 的,就像您的情况一样。

对于 GNU 来说,和 后缀sed之间不应有空格,例如.-i-i''

  • 所以看起来奇怪的字符串s/^CREATE DATABASE.*//是附加到文件名用于保存备份的后缀。

  • 正如您所猜测的,您想要的文件名将world.sql成为要应用的 sed 命令。

  • 由于您没有使用 -e 选项,因此只需要一个命令。当然,可以通过用分号分隔它们并引用参数来提供更多内容。但这与我们无关。

  • 正如您所猜测的,w恰好是一个有效的 sed 命令,用于将模式空间写入文件,该文件的名称是紧随w命令末尾的任何内容。

  • 因此 sed 创建一个名为 的文件,orld.sql准备在执行阶段填充它。

  • 现在命令行上没有任何内容,因此 sed 认为数据来自标准输入。因此,您会看到来自 sed 的消息,在-i模式下您无法从 stdin 获取数据。

答案3

您可以使用神奇的参数--来告诉大多数版本sed(以及许多其他 CLI 工具)您已完成为其提供开关(通常以-或开头--),并且命令行的其余部分应解析为参数。像这样:

$ sed --in-place 's/^CREATE DATABASE.*$//' -- world.sql

不过,在要删除整行的地方使用替换命令可能会更简洁:

$ sed --in-place '/^CREATE DATABASE/d'

您的问题也带有 MacOS 标签。 Mac 使用某些工具的 BSD 版本,而不是sedLinux 中通常包含的版本,并且需要--in-place.但是,如果此参数为空字符串,则其行为与在其他 POSIX 上的行为相同:

$ sed --in-place '' '/^CREATE DATABASE/d'

相关内容