我有这个命令:
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
据我所知,sed
MacOS 上有 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 版本,而不是sed
Linux 中通常包含的版本,并且需要--in-place
.但是,如果此参数为空字符串,则其行为与在其他 POSIX 上的行为相同:
$ sed --in-place '' '/^CREATE DATABASE/d'