在另一个问题中,建议我使用
shopt -s extglob
解决一个问题。我的印象是应谨慎使用这些类型命令,也许是因为它们可能会对其他脚本产生不良影响。有人能谈谈这个吗?
答案1
shopt
只影响运行该命令的 shell 的行为。如果您将其放入~/.bashrc
then,它将影响非登录交互式 shell 和通过 rsh/ssh 运行的命令(如果~/.bashrc
源自~/.profile
或 ,则登录 shell 也可能会受到影响~/.bash_profile
)。
将环境变量设置BASHOPTS
为extglob
将影响设置该环境变量时启动的所有交互式或非交互式 bash shell(除非它们被称为sh
)。
交互式 shell 是您想要extglob
设置的地方,因为那是您想要使用它的地方,因此~/.bashrc
是放置它的好地方,以便在每个交互式 shell 中受益。如果您想在脚本中使用它,只需将其添加到脚本的开头即可。
唯一可能导致问题的地方是当它被设置时,而您没有编写的某些代码并不期望它被设置。例如,这可能是您的脚本来源在出现提示时或在~/.bashrc
设置选项后。
虽然对于某些选项来说确实如此,但事实并非如此,因为extglob
它是经过精心设计的(由 David Korn 设计,来自 ksh),以免破坏与 Bourne shell 的向后兼容性(并解释了为什么语法如此尴尬)。
基本上,任何使用扩展 glob 的内容在 Bourne shell 或 POSIX shell 语法中都会出现语法错误。如果 Bourne 或 POSIX 脚本有echo @(a)
,它将被破坏(因为未加引号的括号)。如果突然开始输出“a”而不是错误消息也没关系。
我不清楚为什么 bash 默认情况下不启用它,因为 bash 没有像 zsh 那样有任何其他替代的扩展 glob 语法。
编辑。虽然 David Korn 努力不破坏 Bourne/POSIX 兼容性,但 bash 看起来并不那么小心,这可能就是它不像 ksh 那样默认启用的原因。
在 ksh(以及 ksh 仿真中的 zsh)中,在参数或命令替换上执行通配符时,扩展通配符被禁用:
$ touch a
$ a='@(a)' ksh93 -c 'echo $a'
@(a)
而在 bash 中,情况并非如此:
$ a='@(a)' BASHOPTS=extglob bash -c 'echo $a'
a