$_ 与 !$。前面命令的最后一个参数和输出重定向

Loo*_*oom 58 shell bash history-expansion

问题是关于特殊变量。文档说:

!!:$

指定前面命令最后一个参数。这可以缩短为!$.


( $_, 下划线。) 在 shell 启动时,设置为绝对路径名,用于调用在环境或参数列表中传递的正在执行的 shell 或 shell 脚本。随后,扩展到扩展后上一个命令最后一个参数。还设置为用于调用在导出到该命令的环境中执行和放置的每个命令的完整路径名。

一定有一些我无法理解的差异,因为:

$ echo "hello" > /tmp/a.txt
$ echo "!$"
echo "/tmp/a.txt"
/tmp/a.txt

$ echo "hello" > /tmp/a.txt
$ echo $_
hello
Run Code Online (Sandbox Code Playgroud)

有什么不同?

cuo*_*glm 64

!$是历史扩展的单词指示符,它扩展到history中上一个命令的最后一个单词。IOW,历史上上一个条目的最后一句话。这个词通常是 command 的最后一个参数,但不是在重定向的情况下。在:

echo "hello" > /tmp/a.txt
Run Code Online (Sandbox Code Playgroud)

整个命令'echo "hello" > /tmp/a.txt'出现在历史中,并且/tmp/a.txt是该命令的最后一个字。

_是一个 shell 参数,它扩展到上一个命令的最后一个参数。在这里,重定向不是传递给命令的参数的一部分,因此只有hello传递给 的参数echo。这就是为什么$_扩展到hello.

_不再是shell 标准的特殊参数之一。它适用于bash, zsh,mksh并且dash仅在交互式时有效,ksh93仅当两个命令位于单独的行上时:

$ echo 1 && echo $_
1
/usr/bin/ksh

$ echo 1
1
$ echo $_
1
Run Code Online (Sandbox Code Playgroud)

  • `!$` 扩展与 `$_` 参数的一个效果是 `echo $_` 在历史中总是显示为 `echo $_`,而 `echo !$` 显示它被扩展到的值。例如`echo one two` 然后`echo !$`,然后按下显示`echo two`。 (11认同)