我有一个值为 6 的变量
$ echo $line_number
6
当我使用 sed 删除除 0 - 6 之外的所有行时,它按预期工作
$ sed "0,6!d" ~/myfile
当我尝试用变量替换数字 6 时,出现错误
$ sed "0,$line_number!d" ~/myfile
bash: !d": event not found
答案1
这里的问题是!
in 中的字符bash
,当交互时,即使在双引号内也会触发历史扩展。
该功能来自 csh(实际上更糟糕),并且在 bash 和 zsh 中也可以找到,但在其他方面不是标准sh
功能。
在bash
and中zsh
,与 相反csh
,历史扩展不会发生在单引号内,因此sed '0,6!d'
没问题。但sed "0,6!d"
还不行。在交互式bash
shell 中,!d
展开到包含d
.
您可以!
通过以下方式删除 的特殊含义:
sed "0,$line_number"'!d'
我个人禁用历史扩展功能,因为现代 shell 具有更好的交互式等效功能。我在zsh
with中禁用了它,您也可以在withset +o banghist
中禁用它(实际上,为了与 1997 年的 3.1.2 兼容而将其添加为别名,因此也可以在 with 中使用)。在 中,您可以使用 禁用历史记录扩展。实际上,等效的方法也适用于和。bash
set +o histexpand
zsh
histexpand
banghist
bash
set +o histexpand
zsh
(t)csh
set histchars
histchars=
bash
zsh
请注意,该0
地址是 GNUsed
扩展。可移植的是,您可以使用head
它(这也会更有效):
head -n "$line_number"
对于sed
可移植的,您可以使用:
sed "${line_number}q"
这也更有效,因为在第sed
行之后停止读取而不是继续读取但丢弃所有其他行。$line_number