6.12 shell 兼容模式(Shell Compatibility Mode)
Bash-4.0 引入了一个 shell 兼容级别的概念,其指定的是 shopt 内建命令的一个选项集合(compat31、compat32、compat40、compat41 等等)。只有一个当前兼容级别生效,即每个选项是互斥的。兼容模式的意图在于允许用户选择使用以前版本的行为,这样在将脚本迁移到与之不兼容的更新版本时可以使用其特性和行为。这只是一个临时解决方案。
这节没有涉及特别版本的行为标准(例如,设置级别 compat32 意味着将正则匹配操作符的右侧操作数引起来就是将在单词中的特殊正则字符引起来,其作为 bash-3.2 及以上版本的默认行为)。
如果一个用户启用了,比如说 compat32,其可以影响到当前兼容级别以及之前的所有其它兼容级别的行为。这个思想是让每一个兼容级别可在该 Bash 版本中控制改变其行为,但这个行为可能只存在于更早的版本中。例如,对于“[[”命令使用基于本地语言的比较是在 bash-4.1 出现的,更早版本是基于 ASCII 的比较,所以在 bash-4.1 中开启 compat32 也会开启基于 ASCII 的比较。这种粒度可能不会满足所有的使用需求,所以作为用户应该小心的选择兼容级别。阅读特定特性文档可以获知其行为。
Bash-4.3 引入了一个新的 shell 变量:BASH_COMPAT。分配给该变量的值(像 4.2 这样的十进制小数,或一个对应于 compatNN 选项中的整数,像 42)确定了兼容级别。
在 bash-4.4 之后,Bash 开始不赞成使用更老版本的兼容级别。最终,这些选项都移入到 BASH_COMPAT 变量中。
Bash-5.0 是可使用单一 shopt 选项设置之前兼容版本的最后一版。用户在 bash-5.0 和之后版本应该使用 BASH_COMPAT 变量进行兼容设置。
下列列表描述的是对于每一个兼容级别的行为变化控制。标记“compatNN”是使用下列机制中的一个来设置到兼容级别“NN”的快捷方式。在 bash-5.0 以前的版本,可以设置相应“compatNN”的 shopt 选项来设置兼容级别。在 bash-4.3 及以后版本,推荐使用 BASH-COMPAT 变量,并且该访求是在 bash-5.1 及以后版本必须使用的。
compat31
- 将“[[”命令的正则匹配操作符“=~”的右侧操作数引起来不会产生任何特殊效果。
compat32
- 在中断像“a ; b ; c”这样的命令列表中的某一命令时,会继续执行列表中的下一条命令。(在 bash-4.0 及以后版本中,shell 的响应就像收到中断一样,所以中断列表中的一个命令就会中止整个列表的执行)
compat40
- “[[”命令中的操作符“<”和“>”在进行比较字符串时是不会参考当前区域语言的;它们使用的是 ASCII 顺序。在 bash-4.1 之前的版本使用 ASCII 校验和“strcmp(3)”;在 bash-4.1 及之后版本使用当前区域语言校验序列和“strcoll(3)”。
compat41
- 在 POSIX 模式中,time 后面是可跟随选项的,并且 time 仍然是会被认为是一个保留字(这是 POSIX 说明 267 号)。
- 在 POSIX 模式中,解析器要求一个偶数单引号出现在双引号中的参数扩展“${…}”中的 word 部分并且对其进行特殊处理,以便在单引号内的字符是被认为是引起来的(这是 POSIX 说明 221 号)。
compat42
- 在双引号样式替换中的替换字符串不会进行引用移除,在 bash-4.2 之后的版本也是如此。
- 在 POSIX 模式中,当扩展在双引号引用的参数扩展“${…}”的 word 部分时,单引号会认为是特殊的,并且可用于将后半个大括号或其它特殊字符引起来(这是 POSIX 说明 221 号);在其后版本中,在双引号单词扩展中的单引号是没有特殊含义的。
compat43
- 如果试图使用引起来的复合赋值语句作为 declare 命令的一个参数(declare -a foo=‘(12)’),shell 不会打印警告消息。其后版本会发出警告,不赞成使用该方法。
- 引起当前命令失败的单词扩展错误会被认为是非至命错误,即使是在 POSIX 模式(默认的行为是认为是致命错误并会引起 shell 退出)。
- 当执行一个 shell 函数时,循环状态(while、until 等等)是不会被重置的。所以在函数中的 break 和 continue 将会中断或继续在调用方上下文中的循环。bash-4.4 及以后版本会重置循环状态以防止这种情况发生。
compat44
- 即使没有开启扩展调试模式,shell 也会设置变量 BASH_ARGV 和 BASH_ARGC 的值为已扩展的 shell 位置参数。
- 一个子 shell 会从其父 shell 的上下文中继承循环,因此 break 和 continue 将会引起子 shell 退出。bash-5.0 及以后版本会重置循环状态以防止其退出。
- 即使 shell 不在 POSIX 模式,在变量赋值语句后面的诸如 export 和 readonly 内建命令对变量所设置的属性会继续对在调用方环境中的相同变量产生作用。
compat50(设置使用 BASH_COMPAT)
- bash-5.1 改变了$RANDOM 的随机方法,使其产生的随机数更随机了一点。如果 shell 兼容级别设置为 50 或更低,其会恢复到 bash-5.0 及以前版本的方式。因此给 RANDOM 分配一个值来产生的随机数生成器将会产生像在 bash-5.0 里一样的序列。
- 如果命令哈希表是空的,早于 bash-5.1 版本的 Bash 会打印一个有效的通知消息,即使当所产生的输出可重用作为输入。bash-5.1 在使用了“-l”选项后,会抑制该消息。