$_ 有好幾個功能,我們最常用的是用它來獲取“剛剛執行過的命令的最後一個引數”這個功能,比如下面這樣:
$ ls ~/Downloads/very/long/dir/ # ls 到某個目錄看看有沒有我們想要的檔案 file1 file2 needed_file $ cd $_ # 如果有,就進入到那個資料夾,$_ 讓你省去了不少鍵盤敲擊數 |
Bash manual 中對 $_ 的這個功能的描述只有一句話:
expands to the last argument to the previous command, after expansion.
惜字如金,讓你覺的這個功能真的很簡單,但稍微深入想一想,如果上次執行的命令完全沒有引數呢?
$ echo # 沒有引數 $ echo $_ echo |
哦哦,這下我們知道了,如果一個引數也沒有,那麼 $_ 就是命令的名字本身。那麼問題又來了,如果命令的名字也沒有呢?有些同學就問了,怎麼寫出一個連命令名也沒有的命令呢。其實在 Shell 裡面,一條簡單命令的組成文法大概是這個樣子的:
賦值語句 命令名和引數 重定向
比如 foo=1 bar baz >qux 就是三個部分都存在的命令,但其實,這個三個部分只要存在一個部分就算是一條簡單命令了,不信我們試試:
$ foo=1 # 只有第一部分,這也是一條命令,很熟悉吧,就是我們常見的賦值語句 $ foo=1 > bar # 沒有第二部分,這也可以 $ >bar # 只有第三部分,還可以 |
下面就說結論了:當沒有命令名和引數這一部分的時候,Bash 會給 _ 賦空值:
$ : foo $ echo $_ # _ 的值是 foo foo $ foo=1 $ echo "左邊$_右邊" # _ 的值被 Bash 賦值為空,這種情況在 zsh 下只是不更新 _ 的值,還是 foo,但不會賦空值 左邊右邊 $ : foo $ > bar $ echo "左邊$_右邊" # 同樣,又被賦值為空,zsh 下還會是 foo 左邊右邊 |
除了這種沒有命令名和引數的場景,還有兩種情況下 Bash 會給 _ 賦空值,一個是包含管道的命令,再一個是後臺(非同步)執行的命令:
$ : foo $ echo 1 | echo 2 2 $ echo "左邊$_右邊" # _ 為空,在 zsh 下會是最後一個管道右邊的命令的最後一個引數,也就是 2 左邊右邊 $ echo 1 & $ echo "左邊$_右邊" # _ 還是空,在 zsh 下沒有特殊處理,是 1 左邊右邊 |
還有一個 Bash 文件沒明確指出的點,那就是隻有簡單命令才會更新 _ 的值,管道命令,命令列表,複合命令這些命令本身,都不會更新 _ 的值,但它們包含的簡單命令要是執行了的話是會影響的(比如 for 迴圈裡的簡單命令沒有執行的話,不會更新 _,反之亦然)。