為歷史擴充模式設定別名

為歷史擴充模式設定別名

與我了解到的現有$_代表類似!-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-wordsmart-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

相關內容