防止 bash 完成更改底線變數 $_

防止 bash 完成更改底線變數 $_

在 bash 中使用製表符補全時,$_變數會被變更:

$ mkdir test
$ cd <TAB><TAB> $_
bash: cd: -d: invalid option
cd: usage: cd [-L|[-P [-e]]] [dir]

<TAB><TAB>將列出當前目錄中的所有文件,但我最終不會使用輸出並寫入$_。在這一行中執行的命令將只是cd $_。)

預期的行為將變為./test

如何防止 bash 完成更改$_

答案1

您正在使用bash-completion包(或衍生性商品)。對於命令的每個參數完成cd(如輸出所示complete -p):

complete -o nospace -F _cd cd

呼叫_cd函數來確定完成情況(為簡潔起見,稍作編輯):

_cd()
{
    local cur prev words cword
    _init_completion || return

    local IFS=$'\n' i j k

    compopt -o filenames

    if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
        _filedir -d
        return 0
    fi
    ....

例如,當您完成未CDPATH設定的目錄時,所見命令的最後一次看到的參數是-d,並且它會自動放置在 中_。該函數中還有其他幾個具有類似副作用的程式碼路徑。

由於_是 bash 內部,因此傳統的保存/恢復(至於IFS)不會像希望的那樣工作。你可以用一點技巧來做到這一點:

_cd()
{
    local save_="$_"
    ...
    : $save_
    return 0

您必須_在進入函數時立即儲存,:這是空命令,它本身不執行任何操作,但具有命令的常見副作用,例如設定_。每個潛在破壞性功能的每個返回點都需要此復原操作。這裡也有一個微妙之處:通常_在函數返回後立即設定(如預期的那樣,到函數呼叫的最後一個參數),這將使方法無效。但是,當呼叫完成函數時不會發生這種情況,因為它不是明確調用的。我不認為這非常強大......

(我比較喜歡歷史擴展,並堅持!$哪個不會遇到這個問題。

相關內容