我正在尝试为我的bashrc创建一个别名,如果没有设置xtrace,它将启用选项nounset和xtrace,如果设置了它们,它将禁用它们,从而允许我切换“调试模式”。
我有这个:
alias debug="[[ \$(set -o | grep xtrace) = *off ]] && (set -o nounset; set -o xtrace; echo 'Debug mode ON') || (set +o nounset; set +o xtrace; echo 'Debug mode OFF')"我的问题是,从终端输出来看,这似乎是可行的,但是当我运行set -o时,nounset和xtrace选项都没有改变。原因是这两个选项都在括号()中,因此这些选项不会应用于当前终端。
例如,这也不起作用(xtrace保持关闭):
(set -o xtrace)我该如何解决这个问题?有没有一种方法可以不带括号地写上面的别名,或者从括号内应用选项?为什么会发生这种情况?
发布于 2018-02-02 09:04:50
$(…)或(set -o ...;)中的圆括号创建子shell。子shell中所做的更改不会对父shell产生任何影响,无论是环境变量还是shell选项。
您似乎想要嘈杂地切换跟踪标志。这也称为-x标志,在$-中可见,该参数包含当前设置的单字母标志。您还可以将set -u和set +u用于set -o nounset选项。
因此,您可以在以下内容上使用一些变体:
alias debug='case "$-" in
(*x*) set +xu; echo "Debug mode OFF";;
(*) set -xu; echo "Debug mode ON";;
esac'如前所述,如果您愿意,可以将其展平到单行上。还有其他方法可以编写,使用if和适当的条件。我仍然喜欢case,但是在使用[[命令进行Bash之前,我已经学会了shell脚本编程。
您还可以使用{和}来代替子shell表示法。因此,对您的脚本的最低限度的更改将是:
alias debug="[[ \$(set -o | grep xtrace) = *off ]] && { set -o nounset; set -o xtrace; echo 'Debug mode ON'; } || { set +o nounset; set +o xtrace; echo 'Debug mode OFF'; }"请注意,在}之前必须有一个'end of command‘-实际上,这意味着换行符或分号。并且{和}必须与周围的符号分开。我不喜欢使用$(set -o | grep xtrace);与使用$-相比,它非常笨重。你可以通过再次使用$-来解决这个问题:
alias debug='[[ ! $- =~ x ]] && { set -o nounset -o xtrace; echo "Debug mode ON"; } || { set +o nounset +o xtrace; echo "Debug mode OFF"; }'当您打开debug时,这有点嘈杂;最好写成:
alias debug='[[ ! $- =~ x ]] && { echo "Debug mode ON"; set -o nounset -o xtrace; } || { set +o nounset +o xtrace; echo "Debug mode OFF"; }'在关闭跟踪的情况下完成echo。当调试当前处于打开状态并准备将其关闭时,您仍然可以看到测试;这是不可避免的。
您还可以使用显式if/then/else/fi
alias debug='if [[ $- =~ x ]]; then set +o nounset +o xtrace; echo "Debug mode OFF"; else echo "Debug mode ON"; set -o nounset -o xtrace; fi'或者将其压缩为:
alias debug='if [[ $- =~ x ]]; then set +xu; echo "Debug mode OFF"; else echo "Debug mode ON"; set -xu; fi'发布于 2018-02-02 09:05:26
alias debug="[[ \$(set -o | grep xtrace) = *off ]] && { set -o nounset; set -o xtrace; echo 'Debug mode ON'; } || { set +o nounset; set +o xtrace; echo 'Debug mode OFF'; }"{ }可以将多个命令组合在一起,而无需像()那样创建子外壳。语法略有不同;您需要确保在{ }和任何单词之间留出空格,否则可能会被解释为{a,b} → a b括号扩展,并且命令需要以; (或&)结尾。
https://stackoverflow.com/questions/48574100
复制相似问题