$_ 和 !$ 有什么区别?

Luk*_*uke 6 bash shell-script bash-expansion

我总是用来!$引用上一个命令的最后一个参数。

例如

~/dir » mkdir birthday
~/dir » cd !$
~/dir » cd birthday
Run Code Online (Sandbox Code Playgroud)

但是我已经开始看到教程$_代替!$

我已经测试了两者,我注意到的唯一区别是微妙的,但它似乎$_会评估和执行命令,而!$会让您在点击之前对输出进行理智检查Enter,但这是$_和之间的唯一区别!$吗?

更新:标记为重复?这个问题可以由建议问题的已接受答案来回答,但这仅仅是因为答案比要求的问题更详细。

搜索是什么_ $是什么意思?确实产生了建议的重复项,但是在询问做了什么之前我已经知道!$,并且没有任何迹象表明该问题也可能回答其他问题。

B L*_*yer 9

运行man bash并搜索部分Special Parameters。因为_你会发现:

在 expand之后扩展到上一个命令的最后一个参数。

稍微详细一点的版本可能是......

扩展到前一个命令的最后一个参数,因为它是由该命令接收的,即在通过 Shell 扩展之后

我认为一些例子会真正有帮助,而不是进一步解释。

示例 1

$ echo "$(date +%s)" # %s is seconds since epoch
1536984661
$ echo $_ !$ "$(date +%s)" # don't hit enter until a few seconds pass
1536984661 1536984665 1536984665
Run Code Online (Sandbox Code Playgroud)

$_获取传递给前一个的实际值,echo因此它解析为过去的秒数。同时,因为!$被简单地替换为最后一个参数的类型值,即"$(date +%s)",它解析为与它后面的参数相同的稍后时间。

示例 2

$ foo='a b c'
$ echo "$foo"  # expands to single arg: 'a b c'
a b c
$ echo "$_"
a b c
$ #---------
$ echo $foo    # expands to three args: a b c
a b c
$ echo "$_"
c
Run Code Online (Sandbox Code Playgroud)

请注意,第二次$foo回显了它没有被引用。所以在传递给echo它之前经历了变量/参数扩展和分词。这种扩展/拆分导致abc作为三个单独的参数传递给echoand 因为$_只分配了我们只看到的最后一个c。(如果!$使用abc仍然会显示,因为它只是替换为您输入的值,即$foo。)

除了上述之外,$_vs有一些更实用的价值,!$因为前者是一个变量。因此,例如,如果最后一个参数是/some/file/path.txt您可以获得它的长度${#_} -> 19,仅提取文件名${_##*/} -> path.txt,更改根${_//some/other} -> /other/file/path.txt等。不能用!$.


最后,请注意,$_在其他上下文中具有不同的含义:

在 shell 启动时,设置为用于调用在环境或参数列表中传递的正在执行的 shell 或 shell 脚本的绝对路径名。

...和...

还设置为用于调用在导出到该命令的环境中执行和放置的每个命令的完整路径名。

...和...

检查邮件时,此参数保存当前正在检查的邮件文件的名称。