Bash Shell选项更改(例如set-o xtrace)不会从括号内应用

Bash Shell选项更改(例如set-o xtrace)不会从括号内应用,bash,shell,sh,Bash,Shell,Sh,我正在尝试为我的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

我正在尝试为我的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…;)
中创建一个子shell。在子shell中所做的更改对父shell没有影响,无论是环境变量还是shell选项

您似乎想要响亮地切换跟踪标志。这也称为
-x
标志,在
$-
中可见,该参数包含当前设置的单字母标志。您还可以使用
set-u
set+u
作为
set-o-set
选项

因此,您可以在以下方面使用一些变体:

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'; }"
请注意,
}
前面必须有一个“命令结束符”—实际上,这意味着换行符或分号。
{
}
必须与周围的符号分开。我不喜欢使用
$(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
是在跟踪关闭时完成的。当调试当前处于打开状态且即将关闭时,您仍然可以看到测试;这是不可避免的

如果/
/
否则
/
/
可以使用显式的
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'

$(…)
(set-o…;)
中的括号创建子shell。在子shell中所做的更改对父shell没有影响,无论是环境变量还是shell选项

您似乎想大声切换跟踪标志。这也被称为
-x
标志,在
$-
中可见,该参数包含当前设置的单字母标志。您还可以使用
set-u
set+u
作为
set-o nounoset
选项

因此,您可以在以下方面使用一些变体:

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'; }"
请注意,
}
前面必须有一个“命令结束符”—实际上,这意味着换行符或分号。
{
}
必须与周围的符号分开。我不喜欢使用
$(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
是在跟踪关闭时完成的。当调试当前处于打开状态且即将关闭时,您仍然可以看到测试;这是不可避免的

如果
/
/
否则
/
/
可以使用显式的
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'
{}
可以将多个命令组合在一起,而无需像
()
那样创建子shell。语法有点不同;您需要确保在
{}
和任何单词之间保留空格,否则它可以解释为
{a,b}→ a b
大括号展开,命令需要以a
;(或
&
)终止


{}
可以将多个命令组合在一起,而无需像
()
那样创建子shell。语法有点不同;您需要确保在
{}
和任何单词之间保留空格,否则它可以解释为
{a,b}→ b
大括号展开,命令需要以
(或
&
)终止。

括号(在
$(…)
(set-o…;)
中)创建子shell。在子shell中所做的更改对父shell没有影响,无论是环境变量还是shell选项。这是需要的、有文档记录的、预期的行为,而不是需要“固定”的行为。括号(在
$(…)
(set-o…;)
中)创建一个子shell。在子shell中所做的更改对父shell没有影响,无论是环境变量还是shell选项。这是需要的、有文档记录的、预期的行为,而不是需要“修复”的内容。