我有一个函数,想使用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 ash
,local
不会影响变量的值或属性(与bash
它最初使它未设置的位置相反)。它仍然以与特殊情况bash
相同的方式工作ash
,即它不会导致$-
取消设置或恢复为默认行为set -o option
,而不是设置的选项shopt -s option
(bash
是唯一具有两组选项的外壳!)与局部变量一样,它是动态范围,而不是静态范围。$-
从函数返回时将恢复的值,但新设置将影响其他函数或由您的函数调用的源脚本。如果你想要静态范围,你需要切换到 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
在其他类似伯恩的贝壳来避免(!)它)......
该$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)