25

我想在我的脚本中临时设置-x,然后恢复到原始状态。

有没有办法在不启动新子外壳的情况下做到这一点?就像是

echo_was_on=.......
... ...
if $echo_was_on; then set -x; else set +x; fi
4

7 回答 7

26

您可以检查 的值$-以查看当前选项;如果它包含一个 x,则它已被设置。你可以像这样检查:

old_setting=${-//[^x]/}
...
if [[ -n "$old_setting" ]]; then set -x; else set +x; fi

万一你不熟悉:${}上面是一个Bash Substring Replacement,它接受变量-并替换任何不是 ax的东西,只留下x后面(或者什么都没有,如果没有 x)

于 2013-01-28T15:10:14.913 回答
13
reset_x=false
if ! [ -o xtrace ]; then
    set -x
    reset_x=true
fi

# do stuff

"$reset_x" && set +x

您使用 test 测试 shell 选项-o(使用[如上或 with test -o)。如果xtrace未设置该选项 ( set +x),则设置它并设置一个标志以稍后将其关闭。

在函数中,您甚至可以设置RETURN陷阱以在函数返回时重置设置:

foo () {
    if ! [ -o xtrace ]; then
        set -x
        trap 'set +x' RETURN
    fi

    # rest of function body here
}
于 2018-06-03T16:05:54.020 回答
11

或在案例陈述中

 case $- in
   *x* ) echo "X is set, do something here" ;;
   * )   echo "x NOT set" ;;
 esac
于 2013-01-28T15:15:04.273 回答
9

以下是基于@shellter@glenn jackman 的答案的可重用函数:

is_shell_attribute_set() { # attribute, like "e"
  case "$-" in
    *"$1"*) return 0 ;;
    *)    return 1 ;;
  esac
}


is_shell_option_set() { # option, like "pipefail"
  case "$(set -o | grep "$1")" in
    *on) return 0 ;;
    *)   return 1 ;;
  esac
}

使用示例:

set -e
if is_shell_attribute_set e; then echo "yes"; else echo "no"; fi # yes

set +e
if is_shell_attribute_set e; then echo "yes"; else echo "no"; fi # no

set -o pipefail
if is_shell_option_set pipefail; then echo "yes"; else echo "no"; fi # yes

set +o pipefail
if is_shell_option_set pipefail; then echo "yes"; else echo "no"; fi # no

更新:对于 Bash,test -o是完成相同任务的更好方法,请参阅@Kusalananda 的回答

于 2016-01-10T18:30:40.987 回答
3

还:

case $(set -o | grep xtrace | cut -f2) in
    off) do something ;;
    on)  do another thing ;;
esac
于 2013-01-29T01:17:11.547 回答
2

不那么冗长

[ ${-/x} != ${-} ] && tracing=1 || tracing=0
于 2018-02-21T09:39:13.767 回答
1

如果您对 bash 扩展(非 POSIX)没问题并且您的 bash 版本支持它,这应该可以准确回答问题。

[[ $- =~ x ]] && echo_was_on=true || echo_was_on=false
于 2020-09-02T18:50:18.023 回答