Zsh

為歷史擴展模式設置別名

  • May 30, 2019

類似於我所$_學的現有代表!-1:$,我想為 , 等創建別名$__$___以引用第二個或第三個 -last 命令。我試過添加

alias "$__"='!-2:$'

在我的.zshrc.local. 如果可能的話,我想寫一個 zsh 函式,它根據下劃線的數量返回第 n 個最後一個命令的第一個參數。

arch linux kernel 5.1.4-arch
zsh 5.7.1 (x86_64-pc-linux-gnu)

此功能已存在

您不需要任何復雜的東西來訪問先前命令的最後一個字。只需按ESC-.(ie Alt+ .) 或ESC-_(ie 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您可能會發現它對按原樣使用或作為程式碼範例很有用。

如果你真的想$__擴展到previous-but-one命令的最後一個單詞,我會在下面給出一些解決方案,但首先我需要解釋一下發生了什麼。

為什麼您的嘗試不起作用

首先,你沒有定義你認為你定義的東西。定義一個別名,其名稱是執行別名定義時alias "$__"=…變數的目前值。__這可能是空的,因此您正在執行查找在搜尋路徑(文件名擴展的擴展部分)上alias ='!-2:$'呼叫的命令。要定義一個名為 的別名,您需要傳遞給 alias 命令,例如 with或。'!-2:$'=$__``$__``alias '$__'=…``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因為_已經被拿走了。並且該函式將最後一個單詞的歷史變數“移動”一個。

darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_ $__ $___
three two one

引用自:https://unix.stackexchange.com/questions/521968