检查 bash 选项

red*_*pet 6 bash shopt

我有一个函数,想使用pipefail里面的选项。但我不想简单地set -o pipefail,因为我担心脚本的另一部分可能不会pipefail被设置。当然我可以set +o pipefail事后做,但如果pipefail设置在我的函数之外,这也可能会引入意外行为。

当然false | true,如果pipefail设置了,我可以使用退出代码作为衡量标准,但这似乎有点脏。

有没有更通用的(也许是规范的?)方法来检查设置的 bash 选项吗?

Sté*_*las 10

bash-4.4上面,您可以使用:

myfunction() {
  local -
  set -o someoption
  ...
}
Run Code Online (Sandbox Code Playgroud)

一些注意事项:

  • 这是从ash. 在 中ash,想法是使$-(存储选项集)本地化。它起作用是ash因为 in ashlocal不会影响变量的值或属性(与bash它最初使它未设置的位置相反)。它仍然以与特殊情况bash相同的方式工作ash,即它不会导致$-取消设置或恢复为默认行为
  • 它只涵盖了设置的选项set -o option,而不是设置的选项shopt -s optionbash是唯一具有两组选项的外壳!)
  • 与局部变量一样,它是动态范围,而不是静态范围。$-从函数返回时将恢复的值,但新设置将影响其他函数或由您的函数调用的源脚本。如果你想要静态范围,你需要切换到 ksh93 并使用:

    function myfunction {
      set -o myoption
      ...
      other_function
    }
    
    Run Code Online (Sandbox Code Playgroud)

    随着other_function不受影响,只要它与声明的function other_function {语法,以及(而不是伯恩other_function()...语法)。

  • 由于它不会重置选项,因此您的功能可能仍会受到其他代码设置的选项的影响。为避免这种情况,您需要zsh改用。zsh相当于local -is set -o localoptions,但您也可以在本地使用众所周知的仿真模式。例如:

    myfunction() {
      emulate -L zsh
      set -o someoption
      ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    将从一组健全的 zsh-default 选项(有一些例外,请参阅文档)开始,您可以在其上添加您的选项。这也是 ash/bash 中的动态范围,但您也可以使用以下命令调用其他函数:

    emulate zsh -c 'other_function...'
    
    Run Code Online (Sandbox Code Playgroud)

    对于other_function与香草的zsh选项集调用。

    也zsh中有一些运营商,可以使你避免在首位全球变化的选项(如同(N)/(D)水珠预选赛nullglob/ dotglob(#i)水珠运营商不区分大小写的通配符,${(s:x:)var}以避免交融与$IFS${~var}请求通配时参数扩展(你需要noglob在其他类似伯恩的贝壳来避免(!)它)......


red*_*pet 6

$SHELLOPTS变量保存所有设置的选项,以冒号分隔。例如,它可能如下所示:

braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
Run Code Online (Sandbox Code Playgroud)

要检查给定的选项,可以执行以下操作:

# check if pipefail is set, if not set it and remember this
if [[ ! "$SHELLOPTS" =~ "pipefail" ]]; then
    set -o pipefail;
    PIPEFAIL=0;
else
    PIPEFAIL=1;
fi

# do something here

# reset pipefail, if it was not set before
if [ "$PIPEFAIL" -eq 0 ]; then
    set +o pipefail;
fi
Run Code Online (Sandbox Code Playgroud)

  • `shopt -q globstar` 查询 `shopt`/`$BASHOPTS` 选项的状态 (3认同)
  • 另请参阅 `[[ -o pipefail ]]` 以测试是否设置了 (`$SHELLOPTS`) `pipefail` 选项。也适用于 ksh 和 zsh (2认同)