不设置$?按 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

相关内容