我知道在将变量传递给 sed 时,应该使用双引号。因此,当我使用 sed 显示给定行号的文件行时:
sed '894!d' cloud.cpp
Run Code Online (Sandbox Code Playgroud)
它有效,但由于我也想将行号 894 作为变量传递给 sed,所以我尝试了:
lnum=894
sed "$lnum!d" cloud.cpp
Run Code Online (Sandbox Code Playgroud)
但它不起作用,甚至具有相同语法的单引号也不起作用:
sed "894!d" cloud.cpp
Run Code Online (Sandbox Code Playgroud)
所以在这种情况下,我如何仍然将变量传递给 sed。
如果您的变量只包含数字,那么您所做的就是正确的:
sed "$lnum!d" cloud.cpp
Run Code Online (Sandbox Code Playgroud)
要将 shell 变量传递给sed
一般,请阅读此答案。
现在,在这种情况下,您已正确完成此操作,但仍然无法正常工作。这归因于您的外壳,这可能是bash
,zsh
或csh
. 这些shell支持历史扩展,用!
(这个特性是原始的csh
,后来被bash
和复制的zsh
)表示。
在bash
, 中zsh
,交互式会话中默认启用历史扩展,并将在双引号内执行。
在zsh
:
$ seq 10 | sed "10!d" # <-- press enter
$ seq 10 | sed "10dash"
Run Code Online (Sandbox Code Playgroud)
就像dash
我历史上的最新命令一样,以d
.
在bash
:
$ seq 10 | sed "10!d"
bash: !d": event not found
Run Code Online (Sandbox Code Playgroud)
因为我在 bash 历史记录中没有任何命令以d
.
您可以关闭历史扩展:
set +H
Run Code Online (Sandbox Code Playgroud)
或者:
set +o histexpand
Run Code Online (Sandbox Code Playgroud)
在bash
和:
set -K
Run Code Online (Sandbox Code Playgroud)
或者:
setopt nohistexpand
Run Code Online (Sandbox Code Playgroud)
在zsh
。
对于更便携的方式,不依赖于你的 shell 选项,你总是可以这样做:
sed "$lnum"\!d cloud.cpp
Run Code Online (Sandbox Code Playgroud)
这会导致您的外壳按!
字面意思处理。
正如您所提到的,您必须使用双引号,因为当您对字符串使用单引号时,其内容将按字面处理。但是在您的情况下,您有模式和变量的组合。所以你应该对模式使用单引号,对变量使用双引号:
sed "$lnum"'!d' cloud.cpp
Run Code Online (Sandbox Code Playgroud)