6.11 Bash的POSIX模式
评论 0
浏览 0
2023-01-26
用--posix命令行选项启动Bash,或者在Bash运行时执行‘set -o posix’,将使Bash更符合POSIX标准,在Bash默认值不同的地方改变行为以符合POSIX所指定的标准。
当以sh
的方式调用时,Bash在读取启动文件后会进入POSIX模式。
下面的列表是当‘POSIX模式’生效时的变化内容。
- Bash确保
POSIXLY_CORRECT
的变量被设置。 - 当哈希表中的一个命令不再存在时,Bash会重新搜索
$PATH
来找到新的位置。这也可以用‘shopt -s checkhash’。 - Bash不会在命令哈希表中插入一个没有设置执行位的命令,即使它作为
$PATH
搜索的(最后的)结果返回了它。 - 当一个作业以非零状态退出时,作业控制代码和内置程序所打印的信息是‘Done(status)’。
- 当作业被停止时,作业控制代码和内置程序打印的信息是‘Stopped(signame)’,其中signame是,例如,
SIGTSTP
。 - 别名扩展总是被启用的,即使在非交互式shell中也是如此。
- 出现在保留词被认可的语境中的保留词不进行别名扩展。
- 别名扩展是在最初解析命令替换时进行的。 默认模式下,如果启用,一般会推迟到命令替换执行时进行。这意味着命令替换不会扩展在最初解析命令替换后定义的别名(例如,作为函数定义的一部分)。
- 启用了POSIX
PS1
和PS2
扩展,即‘!’到历史编号和‘!!’到‘!’的扩展,并且无论promptvars
选项的设置如何,都对PS1
和PS2
的值进行参数扩展。 - POSIX启动文件被执行(
$ENV
),而不是正常的Bash文件。 - 波浪号扩展仅对命令名称之前的赋值执行,而不是对行中的所有赋值语句执行。
- 默认的历史文件是~/.sh_history(这是
$HISTFILE
的默认值)。 - 除非shell是交互式的,否则重定向操作符不会对重定向中的字进行文件名扩展。
- 重定向运算符不对重定向中的词进行分词。
- 函数名称必须是有效的 shell 名称。 也就是说,它们不能包含字母、数字和下划线以外的字符,并且不能以数字开头。 使用无效名称声明函数会导致非交互式 shell 中出现致命语法错误。
- 函数名称可能与POSIX特殊内置程序之一不一样。
- POSIX特殊的内置程序在命令查询过程中会在shell函数之前被发现。
- 当打印shell函数的定义时(例如,通过
type
),Bash不会打印function
关键字。 - 在
PATH
变量的元素中作为第一个字符出现的文字符号不会像上面2 波浪号扩展项下所描述的那样被扩展。 time
保留字本身可以作为一个命令使用。当以这种方式使用时,它显示shell和其完成的子程序的时间统计。TIMEFORMAT
变量控制计时信息的格式。- 当解析和扩展出现在双引号内的${…}扩展时,单引号不再是特殊的,不能用来引用收尾括号或其他特殊字符,除非该操作符是定义为执行模式移除的操作符之一。在这种情况下,它们不必作为匹配对出现。
- 如果下一个标记以‘-’开头,解析器不会将
time
识别为一个保留字。 - ‘!’字符不会在双引号字符串中引入历史扩展,即使
histexpand
选项已被启用。 - 如果一个POSIX特殊的内置程序返回一个错误状态,一个非交互式的shell就会退出。致命的错误是那些在POSIX标准中列出的,包括诸如传递不正确的选项、重定向错误、命令名前面的赋值的变量赋值错误,等等。
- 如果在赋值语句后面没有命令名称时发生变量赋值错误,非交互式shell会以错误状态退出。 例如,当试图给一个只读变量赋值时,就会发生变量赋值错误。
- 如果在特殊内置程序前面的赋值语句中发生了变量赋值错误,非交互式shell会以错误状态退出,但在任何其他简单命令中都不会。对于任何其他的简单命令,shell中止执行该命令,并在顶层继续执行("shell不应对发生错误的命令进行任何进一步处理")。
- 如果
for
语句中的迭代变量或select
语句中的选择变量是一个只读变量,那么非交互式的shell将以错误状态退出。 - 如果
.
filename中的filename没有找到,非交互式的shell就会退出。 - 如果算术扩展中的语法错误导致无效的表达式,非交互式的shell会退出。
- 如果发生参数扩展错误,非交互式shell就会退出。
- 如果用
.
或source
内置程序读取的脚本或用eval
内置程序处理的字符串出现语法错误,非交互式shell就会退出。 - 虽然变量指示是可用的,但它不能应用于‘#’和‘?’的特殊参数。
- 在扩展为双引号的模式上下文中扩展‘*’特殊参数时,不会将
$*
当作双引号来处理。 - 在POSIX特殊内置程序前面的赋值语句,在内置程序完成后会持续存在于shell环境中。
command
内置函数并不阻止将赋值语句作为参数的内置函数将其扩展为赋值语句;当不在POSIX模式下时,赋值内置函数在command
之前会失去其赋值语句的扩展属性。bg
内置程序使用所需的格式来描述放置在后台的每一项工作,其中不包括指示该工作是当前的还是前一个工作。- ‘kill -l’的输出将所有的信号名称打印在一行中,用空格隔开,没有‘SIG’的前缀。
kill
内置函数不接受带有‘SIG’前缀的信号名称。export
和readonly
内置命令以POSIX所要求的格式显示它们的输出。trap
内置程序显示的信号名称不含前导词SIG
。trap
内置程序不会检查第一个参数是否为可能的信号规范,如果是,则将信号处理恢复到原来的处理方式,除非该参数仅由数字组成,并且是一个有效的信号编号。如果用户想将给定信号的处理程序重置为原始处理方式,他们应该使用‘-’作为第一个参数。trap -p
显示那些处置方式被设置为SIG_DFL的信号,以及那些在shell启动时被忽略的信号。- 如果
.
和source
内置函数通过搜索PATH
找不到文件名参数,则不会搜索当前目录。 - 启用POSIX模式具有设置
inherit_errexit
选项的效果,因此为执行命令替换而产生的子shell会继承父shell的-e选项的值。 当inherit_errexit
选项未被启用时,Bash会清除此类子壳中的-e选项。 - 启用POSIX模式具有设置
shift_verbose
选项的效果,所以shift
的数字参数如果超过了位置参数的数量,将导致错误信息。 - 当
alias
内置程序显示别名定义时,除非提供了-p选项,否则它不会显示带有前导符的‘alias’。 - 当
set
内置程序在没有选项的情况下被调用时,它不会显示shell函数的名称和定义。 - 当
set
内置程序被调用而没有选项时,它会显示不带引号的变量值,除非它们包含shell元字符,即使结果包含非打印字符也如此。 - 当
cd
内置程序在逻辑模式下被调用时,由$PWD
和作为参数提供的目录名构建的路径名并不指向一个现有的目录,cd
将失败,而不是退回到物理模式。 - 当
cd
内置程序不能改变一个目录时,因为从$PWD
和作为参数提供的目录名构建的路径名的长度超过了PATH_MAX
,当所有符号链接被展开时,cd
将失败,而不是试图只使用所提供的目录名。 pwd
内置程序会验证它所打印的值是否与当前目录相同,即使它没有被要求用-P选项来检查文件系统。- 在列出历史记录时,
fc
内置程序不包括历史记录是否被修改的指示。 fc
所使用的默认编辑器是ed
。type
和command
内置程序不会报告发现了一个不可执行的文件,尽管如果它是$PATH
中发现的唯一一个如此命名的文件,shell将尝试执行这样的文件。- 当运行‘v’命令时,
vi
编辑模式将直接调用vi
编辑器,而不是检查$VISUAL
和$EDITOR
。 - 当
xpg_echo
选项被启用时,Bash不会试图将echo
的任何参数解释为选项。每个参数都会在转换转义字符后显示出来。 - 对于-c和-f选项,
ulimit
内置程序使用的块大小为512字节。 - 当
SIGCHLD
在SIGCHLD
上设置了一个陷阱时,SIGCHLD
的到来并不会打断wait
的内置程序并使其立即返回。 陷阱命令对每一个退出的子程序运行一次。 read
内置程序可能会被一个已经设置了陷阱的信号打断。 如果Bash在执行read
的时候收到了一个陷阱信号,那么陷阱处理程序就会执行,并且read
会返回一个大于128的退出状态。printf
内置程序使用double
(通过strtod
)来转换对应于浮点转换指定符的参数,而不是long double
(如果它’可用)。‘L’长度修改器迫使printf
使用long double
(如果它可用)。- Bash在使用
wait
内置程序获得一个已退出的后台进程的状态后,会将其从此类状态的列表中删除。
还有一些POSIX的行为,即使在POSIX模式下,Bash也没有默认实现。 具体来说。
- 如果
FCEDIT
没有设置,fc
内置程序会检查$EDITOR
作为编辑历史条目的程序,而不是直接默认为ed
。如果EDITOR
没有设置,fc
会使用ed
。 - 如上所述,Bash需要启用
xpg_echo
选项才能使echo
内置程序完全符合要求。
通过在构建时将--enable-strict-posix-default指定为configure
,可以将Bash配置为默认符合POSIX的标准(参见10.8 可选择的功能)。
0 个评论