我添加了set -u
(相当于set -o nounset
).bashrc
,但现在一些选项卡自动完成失败,并出现有关未设置变量的错误。一个例子是git
自动完成。
这是否是一个自动完成错误,或者在交互式终端中git
使用通常是一个坏主意?set -u
有没有其他方法可以在不破坏自动完成功能的情况下保护自己?
(我在 Windows/cygwin 和 RHEL 上使用“git bash”时遇到同样的问题。)
答案1
set -u
来自 Bourne shell 或更明确的set -o nounset
来自 Korn shell(两者都是 POSIX)更多的是一种编程工具,用于检测代码中的拼写错误或初始化变量的使用。
这是编程风格的选择。一旦设置,您就不能让代码取消引用未设置的变量,这意味着您必须以不同的方式编写代码。
例如,您不能:
if [ -n "$TERM" ]; then
echo running in a terminal
fi
您需要解决nounset
with${TERM-}
代替$TERM
或 use 的问题[[ -v TERM ]]
。
有些与大多数其他选项一起使用,例如errexit
orfailglob
或 ,pipefail
它们改变了 shell 的工作方式,并且代码编写者需要调整他们的代码。
现在,在交互式 shell 中,如果您不使用其他人编写的代码,那么这不会成为问题。
问题是 bash 没有相当于 zsh 的emulate -L
功能,第三方函数可以为自己的代码显式请求本地合理的选项基线。
在 zsh 中,完成代码通常执行以下操作:
some-completion-function() {
emulate -L zsh # default set of options in the zsh emulation set locally
set -o extendedglob -o errreturn # additional local options as needed
code here not impacted by the users options
}
bash 中没有等效项,虽然最近版本的bash
has local -
(来自 ash)可以为 所设置的选项设置本地范围set
,但 . 所设置的选项没有等效项shopt
。由于没有等效的emulate
,您需要将所有选项硬编码为其默认值,其列表随 bash 版本而变化。
值得一提的是,bash_completion(这是一个独立于 bash 本身的独立项目)全局更改默认选项(不仅是其自身),并且希望您不要更改它。例如,它设置extglob
和progcomp
。
您会发现它有时会临时设置选项,例如verbose
,noglob
或者nullglob
通过将旧设置保存在变量中并随后恢复来笨拙地设置选项。
在 bash 和 zsh 中,甚至有一些选项会影响代码的解析方式,因此应在加载完成代码(或任何第三方代码)后设置这些选项。在zsh中,大部分补全代码是自动加载第一次使用时,自动加载可以独立于用户的选项或别名(-z
以及-U
的选项autoload
)来完成,但同样在 bash 中没有等效项。
因此,您会发现有很多选项一旦更改了默认值,就会导致 bash 完成失败(noglob
、nounset
、errexit
、errreturn
,failglob
可能还有更多)。更改$IFS
IIRC 值也会导致问题(或至少习惯于)。虽然其中一些可能被认为是 bash_completion 的错误,但在大多数情况下,你不能真正责怪它们,因为问题是 bash 没有工具来应对不同选项集的要求。
因此,如果您要更改选项,请做好在 shell 中使用的某些第三方代码失败的准备。