不設定$?按 Control+C 變成非零

不設定$?按 Control+C 變成非零

Zsh 中的My$PS1包含此表達式:%(?. %?.) 它的意思是「如果前一個命令 ( $?) 的退出代碼為 true,則顯示$?,否則不顯示任何內容」。這通常很有用,但有一件事讓我煩惱:當我按 Control+C 而不運行命令時,shell 將最後一個命令的返回代碼設為非零! Zsh 將其設為 1,Bash 將其設為 130。 Dash 是我的系統上唯一不會在 Control+C 上重設它的 shell。

如何重現:

  1. 啟動 zsh 或 bash。
  2. 按 Control+C。
  3. echo $?

有沒有辦法在 Zsh 上關閉這種行為?

答案1

我不認為有任何方法可以將其關閉。

首先想到的是讓 preexec 設定一個變數來指示命令已運行。如果您在提示時按 Ctrl+C,則不會進行設定。

precmd() {
    exit_status=$?
    if ! $ran_something; then
        exit_status=0
    fi
    ran_something=false
}
preexec() {
    ran_something=true
}
show_non_zero_exit_status() {
    case $exit_status in
    0)
        :;;
    *)
        echo $exit_status;;
    esac
}
PS1='$(show_non_zero_exit_status)$ '

但還有另一個類似的問題:如果您暫停命令,您將獲得退出狀態 20 (zsh < 5.0.7) 或 148(bash 和 zsh >= 5.0.7)。

為了解決這個問題,您可以將其添加20|148case上面的語句中,即

show_non_zero_exit_status() {
    case $exit_status in
    0|20|148)
        :;;
    *)
        echo $exit_status;;
    esac
}

如果您使用 zsh,請確保您setopt promptsubst.zshrc.

如果您使用的是 bash,請新增:

PROMPT_COMMAND=precmd
trap preexec DEBUG

但實際上你應該要使用中提到的更複雜的DEBUG陷阱https://superuser.com/a/175802/15334

另一種可能性是它setopt printexitvalue夠接近你想要的。

答案2

希望這個問題在 2019 年仍然能引起人們的興趣...

130是一個非常罕見的退出狀態(我相信早期實現的 UNIX 只能識別最多 128 的退出狀態) - 所以忽略它。

# pseudocode

if exit_status == 0 then
    do nothing
else
    if exit_status == 130 then
        do nothing
    else
        print " [red]exit_status[/red]"

zsh術語而言,它可以翻譯為:

%(0?..%(130?.. %F{red}%?%f))

更新:您編寫的zsh將退出代碼設定為1onCtrl-Cbashto 130。在這裡,2019 年,bash和都zsh回歸130

相關內容