【问题标题】:Bash Exit Status Always Fails ComparisonBash 退出状态总是比较失败
【发布时间】:2020-04-29 05:46:10
【问题描述】:

在我的 .bashrc...

46 function exitstatus()
47 {
48  local a=0
49  local s=$1
50  s=$s+1
51  a=$a+1
52  echo -n ' arg1='$s' a='$a
53  s=$1
54  a=0
55  echo  ' arg1='$s' a='$a
56
57  if [[ "$s" = "$a" ]]; then
58      echo "true"
59  else
60      echo "false"
61  fi
62 }
63
64 function myprompt {
65  local        ss=\$?
66  unset PS1
67  PS1="exit:\$? var:$ss exitstatus $ss $(exitstatus $ss) \n\t $ "
68 }
69 myprompt

exitstatus 的计算结果始终为 false,即使变量 sa 看起来是相同的字符串:

23:36:55 $ true
exit:0 var:0 exitstatus 0  arg1=0+1 a=0+1 arg1=0 a=0
false
23:36:56 $ false
exit:1 var:1 exitstatus 1  arg1=1+1 a=0+1 arg1=1 a=0
false

第 50 行和第 52 行已向我证明 s 被视为字符串,因此我将其作为第 57 行中的字符串进行比较。如果我将 s 与自身进行比较或将 a 与本身,因为 exitstatus 总是评估为true。出于某种原因,exit status $? 作为 exitstatus 的参数没有按我的预期处理。

我错过了什么?

【问题讨论】:

  • 除了你的函数过于复杂(我会把比较写成if (( s == 0 )); then ...),我无法重现这个问题。当然奇怪的是,您似乎在 .bashrc 中设置了一次 PS1 并且从未重置它(您何时再次调用 myprompt?),但这并不能解释您发布的输出。如果你在命令行s=0; a=0; [[ "$s" = "$a" ]] && echo true 上尝试,你会得到什么?而且,我不会将exitstatusecho 语句混在一起,而是通过在set -x 下运行它来调试它。
  • exitstatus 函数只运行一次,当myprompt 运行时(尝试declare -p PS1 看看它设置了什么)。要使其在每次显示提示时运行,请使用PS1="... \$(exitstatus $ss) ... 而不是PS1="... $(exitstatus $ss) ...。尽管实际上这整件事比它应该的要复杂得多。至少,不要乱用转义的美元符号和ss 变量,只需将PS1 设置为单引号字符串。
  • 我发布了一个答案,解释了为什么你会得到一个静态的false 或静态的true。我也会帮你写一个更好的exitstatus(),但我真的不明白你想用$a$s 做什么。如果您发布最终要求(例如“我的提示应该做......”),我很乐意为您提供帮助。
  • 最终,我希望我的提示符显示日期、我的用户名、我正在使用的主机、密码、新行以及绿色或红色文本的时间,具体取决于成功最后一个命令。这些问题让我怀疑单引号没有正确插入颜色转义字符,这就是我改用双引号的原因。

标签: bash prompt ps1 exitstatus


【解决方案1】:

由于您使用双引号定义了PS1="...",因此子shell $(exitstatus ...) 仅在shell 启动时被评估一次。在那之后,那一次评估的结果就是你提示的文字部分,不会再改变了。

小例子

在这个交互式 shell 会话中,我每秒执行一个命令。 date +%s 打印当前时间的秒数。我使用true 作为命令,因为它什么也不打印。

$ PS1="$(date +%s) "
23 true
23 true
23 PS1='$(date +%s) '
26 true
27 true

正如我们所见,使用双引号时,子shell 只计算一次,而使用单引号时,每次打印提示时都会扩展子shell。当然你也可以写PS1="\$(date +%s) "来获取更新提示。

【讨论】:

  • 最初我用单引号分配 PS1 并且与退出状态的比较正确发生,但是......我的提示颜色没有按需要改变。我假设单引号没有正确插入我的 e[m 颜色转义,但我只是再次尝试它并且它起作用了。我认为使用双引号执行 exitstatus 的结果不会随着每个命令的执行而更新,而是保留在采购 .bashrc 之前执行的最后一个命令的结果。
【解决方案2】:

这就是最终奏效的方法。我摆脱了 myprompt 并使用 exitstatus 来更改提示的颜色:

function exitstatus { if [[ $? != 0 ]]; then echo -e "\e[48;5;52m"; fi; }
unset PS1 PS2 PS4
PS1='$(exitstatus) $'

【讨论】:

    猜你喜欢
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-25
    • 2016-02-08
    相关资源
    最近更新 更多