與我了解到的現有$_
代表類似!-1:$
,我想為 等創建別名$__
,$___
以此類推,引用第二個或第三個 -last 命令。我嘗試過添加
alias "$__"='!-2:$'
在我的.zshrc.local
。如果可能的話,我想寫一個 zsh 函數,它根據下劃線的數量傳回第 n 個最後命令的第一個參數。
arch linux kernel 5.1.4-arch
zsh 5.7.1 (x86_64-pc-linux-gnu)
答案1
該功能已經存在
您不需要任何複雜的操作即可存取先前命令的最後一個單字。只需按ESC-.
(即Alt+ .)或ESC-_
(即Alt+ _)。這將調用編輯器命令insert-last-word
,它插入上一個命令列中的最後一個單字。再次按下該鍵可從命令列取得先前的最後一個單詞,依此類推。如果您按了ESC-.
太多次,請使用C-_
(取消)回到先前的單字。
在 vi 模式下,該命令預設不會與按鍵綁定,但您可以使用bindkey
.
您可以傳遞一個數字參數來獲取不同的單字:正數從右側開始(1 是最後一個單字),零或負數從左側開始(0 是第一個單詞,通常是命令名稱,1 是命令名稱)第一個參數之後的單詞,等等)。例如,ESC . ESC - ESC 1 ESC .
插入倒數第二個指令的第一個參數。
透過在 周圍定義您自己的小部件,可以對此命令進行許多變體zle insert-last-word
。 Zsh 附帶copy-earlier-word
和smart-insert-last-word
您可能會發現它對於按原樣使用或作為程式碼範例很有用。
如果您確實想$__
擴展到前一個命令的最後一個單詞,我將在下面給出一些解決方案,但首先我需要解釋一下發生了什麼。
為什麼你的嘗試不起作用
首先,你並沒有定義你認為你正在定義的東西。定義一個別名,其名稱是執行別名定義時alias "$__"=…
變數的目前值。__
這可能是空的,因此您正在執行alias ='!-2:$'
查找'!-2:$'
在搜尋路徑上呼叫的命令(=
擴張檔案名稱擴充的一部分)。要定義名為 的別名$__
,您需要傳遞$__
給別名命令,例如 withalias '$__'=…
或alias \$__=…
。
其次,別名僅在命令位置擴展,即作為命令的第一個單字(在任何前導變數賦值和重定向之後)。為了使這個別名有用,它需要是一個全域別名:alias -g '$__'=…
第三,這個別名不會做任何有用的事情,因為別名擴展發生在歷史擴展之後。
darkstar
darkstar% alias -g '$__'='!-2:$'
darkstar% echo $__
!-2:$
$_
不“代表” !-1:$
。$_
和!-1:$
是在常見情況下存取相同資訊的兩種方法。你可以說$_
“是一個別名” !-1:$
,或者相反,!-1:$
“是一個別名” $_
,但這是在一般英語意義上使用“別名”,而不是在shell 別名的技術意義上,而且它是不精確的,因為兩者不' t 總是具有相同的值。!-1:$
是一個歷史擴展( !
) 構造擴展到遺言(:$
) 的上一個命令列( -1
)。$_
是一個parameter expansion
使用參數_
shell 將其設定為上一個指令的最後一個參數。如果您執行的命令列不完全是一個簡單的命令,則會產生影響,例如:
darkstar% for x in 1 2 3; do echo $x; done
1
2
3
darkstar% echo $_ is not !-1:$
echo $_ is not done
3 is not done
darkstar% echo $_ and !-1:$ are different; echo $_ and !-1:$ are different
echo $_ and done are different; echo $_ and done are different
done and done are different
different and done are different
$__
每個命令定義
您可以定義一個陷阱功能被稱為TRAPDEBUG
它在執行每個命令之前運行。記住 的目前值$_
(請注意,您必須先執行此操作,因為陷阱內的第一個命令將覆蓋_
),然後「移動」多下劃線變數。
darkstar% TRAPDEBUG () { _0=$_; ___=$__; __=$_1; _1=$_0; }
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_,$__,$___
three,two,one
$_1
並不總是與 相同$_
,因為調試陷阱不會在導致_
設置的完全相同的情況下運行,但它非常接近。
$__
每個命令列定義
您可以註冊一個鉤子函數在輸入命令列之前或之後運行。在這種情況下,要么precmd
或者preexec
。它們分別在執行命令之前和之後運行。
preexec_set_underscore_variables () {
___=$__
__=$_1
_1=$historywords[1]
}
preexec_functions+=(preexec_set_underscore_variables)
我用historywords
從命令列獲取最後一個單字。我把它存放起來,_1
因為_
已經被佔用了。該函數將最後一個單字歷史變數「移動」1。
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_ $__ $___
three two one