B

basename——显示文件路径名的基本文件名

语法格式

        basename name [suffix]
        basename [--help] [--version]

命令简介

basename命令主要用于显示文件路径名剔除目录部分后的基本文件名。如果指定了后缀参数suffix,同时也删除文件名的扩展名。其中,name是文件的路径名,suffix是文件名的后缀。

命令选项

        --help     显示命令的简单说明与用法等帮助信息,然后退出。
        --version  显示命令的版本与作者等信息,然后退出。

应用实例

1.显示文件路径名/usr/bin/sort的基本文件名sort。

        $ basename /usr/bin/sort
        sort
        $

2.显示文件路径名/usr/include/stdio.h的基本文件名,同时删除其扩展名“.h”。

        $ basename /usr/include/stdio.h .h
        stdio
        $

bash——GNU Shell

语法格式

        bash [-abefhiklmnprstuvx] [-c string] [[-+]O [shopt_opt]] [gnu-opts] [file]
        bash [--help] [--version]

命令简介

bash是一个与Bourne Shell、Korn Shell兼容的命令解释语言,能够执行读自标准输入或文件的命令。bash吸收了Korn Shell与C Shell的所有优点,因而功能更强。

bash实现了IEEE POSIX 1003.1标准定义的Shell与实用程序部分。可以把bash配置成完全兼容于POSIX标准的Shell。

除了set内置命令中描述的单字符Shell选项,bash还支持“命令选项”一节支持的命令选项。此外,bash也支持多字符的GNU选项。如果需要在命令行上指定GNU长选项,必须出现在传统的单字符选项前面。

命令选项

        -c string             读取并执行字符串参数string中包含的命令。如果string之后还存在其他参数,
                             可以赋予从$0开始的位置参数。
        -i                   表示以交互方式运行bash。
        -l,--login           以注册Shell的方式运行bash。
        -r                   表示以限制的方式运行bash。
        -s                   如果指定了“-s”选项,或命令选项之后再没有命令参数,意味着从标准输入读
                             取命令。以交互方式调用bash时,利用这个选项可以设置位置参数。
        -v,--verbose         显示bash读取的输入数据。
        [-+]O[shopt_opt]     shopt_opt是shopt内置命令能够接受的Shell选项之一。如果shopt_opt存在,
                             “-O”表示设置相应选项的值,“+O”表示清除相应选项的设置。如果未提供
                             shopt_opt,在标准输出显示内置命令能够接受的Shell选项名及其值。如果调用
                             时指定的选项是“+O”,则以能够重用的格式显示Shell选项。
        -,--                 表示选项到此结束,禁止再做选项处理。“-”或“--”之后的参数均作为文件
                             名和命令参数处理。
        --init-file file,--rcfile file 如果bash处于交互方式,执行指定文件file而非标准的用户初始化文件~/.bashrc
                             中的命令。
        --noediting          当bash处于交互方式时,禁止使用GNU readline函数读取命令行。
        --noprofile          禁止读取系统启动文件/etc/profile或任何用户初始化文件~/.bash_profile、
                             ~/.bash_login以及~/.profile。通常,当作为注册Shell调用bash时,bash会自动
                             读取上述文件。
        --norc               如果bash处于交互方式,禁止读取并执行用户初始化文件~/.bashrc。如果采用
                             sh命令调用bash,启用这个选项是默认的动作。
        --posix              改变bash的默认处理方式,使之遵循POSIX标准。
        --restricted         以限制的方式运行Shell。

命令参数

除了命令选项,如果还存在命令参数,且未指定“-c”或“-s”选项,假定第一个参数是一个包含Shell命令的文件名。如果以这种方式调用bash,$0是脚本文件的名字,其余的参数是$1、$2等位置参数。bash读取并执行脚本文件中的命令,然后终止运行,bash的结束状态是脚本文件中最后执行的一个命令的结束状态。如果未执行任何命令,bash的结束状态是0。在运行过程中,bash首先会尝试打开当前目录中的脚本文件,如果文件不存在,bash将会从PATH变量定义的目录中检索指定的脚本文件。

调用方式

注册Shell是参数0的第一个字符为“-”,或使用“--login”选项启动的Shell。

交互Shell是未加任何命令参数,也未指定“-c”选项(其标准输入、标准输出和标准错误输出为终端)的Shell,或使用“-i”选项启动的Shell。交互Shell将会设置PS1变量,“$-”变量包含字符i。利用后者,Shell脚本或启动文件可测试Shell的运行模式。

下面说明了bash怎样处理其启动文件(或称初始化文件),其中的波浪号“~”表示用户主目录,参见“波浪号替换”一节。如果任何启动文件存在但不可读,bash将输出一条错误信息。

当以交互式注册Shell调用bash时,或以“--login”选项作为非交互式Shell运行时,如果存在,bash首先会读取并执行/etc/profile文件中的命令。之后,bash依次检索~/.bash_profile、~/.bash_login和~/.profile文件,如果存在且是可读的,则依次读取并执行其中的命令。如果指定了“--noprofile”选项,将会禁止bash在启动时读取并执行上述文件。

当注册Shell终止运行时,如果存在,bash会读取并执行~/.bash_logout文件中的命令。

当交互Shell(非注册Shell)开始启动时,如果存在,bash会读取并执行~/.bashrc文件中的命令。如果指定了“--norc”选项,将会禁止bash读取并执行~/.bashrc文件。而“--rcfile”选项可以强制bash读取并执行指定文件而非~/.bashrc文件中的命令。

当以非交互方式启动bash时,如运行Shell脚本时,bash首先会检查BASH_ENV环境变量,如果存在,替换其变量值,使用替换后的变量值作为启动文件的名字,读取并执行文件中的命令,其效果就像执行“if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi”命令。注意,bash并不使用PATH变量的值检索文件,也就是说,文件必须位于当前目录才能执行。

当以sh的名义调用Shell时,bash将会尽可能地尝试模拟早期版本的sh的启动过程,同时也遵循POSIX标准。当以交互式注册Shell调用bash或使用“--login”选项运行非交互Shell时,bash首先会依次尝试读取并执行/etc/profile与~/.profile文件中的命令。如果指定了“--noprofile”选项,将会禁止执行前述启动文件。当以sh的名义调用交互式Shell时,bash会检索ENV变量,如果已经设置,则替换ENV变量的值,使用替换后的变量值作为启动文件,读取并执行其中的命令。由于当以sh名义调用Shell时,bash不会尝试读取并执行任何启动文件,故“--rcfile”选项没有任何影响。使用sh名义调用的非交互Shell不会尝试读取其他任何启动文件。当以sh名义调用Shell时,bash将会在读取启动文件之后进入POSIX模式。

当使用“--posix”选项启动,以POSIX模式运行bash时,bash将会遵循POSIX标准,读取并运行启动文件。在此模式下,交互Shell使用ENV变量的值作为启动文件,读取并执行文件中的命令。此外不再考虑其他启动文件。

在开始运行时,bash还会尝试确定其标准输入等连接的是否为网络设备。如果确实如此且可读的~/.bashrc文件存在,bash将会读取并执行其中的命令。但如果是以sh的名义调用的,则不考虑~/.bashrc启动文件。使用“--norc”选项可以禁止bash读取并执行~/.bashrc文件。而“--rcfile”选项可以强制bash读取并执行其他文件中的命令。

在启动Shell时,如果有效的用户ID不等于真实的用户ID,也未指定“-p”选项,bash不会读取和执行任何启动文件,不会继承工作环境中的Shell函数,不管存在与否,忽略SHELLOPTS、BASHOPTS, CDPATH和GLOBIGNORE等环境变量,把有效的用户ID设置成真实的用户ID。如果调用bash时指定了“-p”选项,bash的启动情况类似,但不会重设有效的用户ID。

术语定义

        空白字符 空格或制表符
        单字(word) 单字由一组连续的字符组成,可以作为一个单一的整体处理。
        名字(name) 名字也称作标识符,是一个由字母、数字或下画线组成,以字母或下画线为首字符的
                      单字。
        元字符        未引用时用作分隔单字的字符称作元字符,其中包括“|”、“&”、“;”、“(”、
                      “)”、“﹤”、“>”、空格和制表符。
        控制运算符    控制运算符是用于执行控制功能的标记符“||”、“&”、“&&”、“;”、“;;”、“()”、
                      “||&”或换行符之一。

保留字

保留字是对Shell具有特殊意义的单字。如果未加引用,也不是简单命令的第一个单字以及case与for命令的第三个单字,下列单字是bash认可的保留字:

!、case、do、done、elif、else、esac、fi、for、function、if、in、select、then、until、while、{、}、time、[[及]]。

Shell语法

简单命令

一个简单命令是由选用的变量赋值、一系列由若干空白字符分隔的单字、重定向符号和控制运算符组成的字符序列。其中,第一个单字指定了需要执行的命令,作为参数0 传递给Shell。其余的单字是传递给的命令的选项与参数。

简单命令的返回值是命令的结束状态或128+n(如果命令是由于信号n终止的)。

管道

管道是由一个或多个中间加“|”或“|&”控制运算符的命令组成的命令序列。管道的语法格式如下:

      cmd | cmd2 | cmd3

第一个命令cmd的标准输出通过管道连接到第二个命令cmd2的标准输入,第二个命令cmd2的标准输出通过管道连接到第三个命令cmd3的标准输入,以此类推。这种连接是在命令本身指定的任何重定向之前执行的。如果使用的管道符号是“|&”而非“|”,前一个命令的标准错误输出通过管道连接到后一个命令的标准输入,这是“2>&1 |”的缩写形式,蕴含着标准错误输出的重定向是在命令本身指定的任何重定向之前执行的。

管道的返回值是最后一个命令的结束状态,除非启用了pipefail选项(参见set内置命令)。如果启用了pipefail选项,管道的返回值是最后一个返回非0结束状态的命令的返回值。否则,如果管道中的所有命令均成功地执行,返回0。在返回数值之前,Shell将会等待管道中的所有命令终止运行。

此外,管道中的每个命令都是作为一个单独的进程在子Shell中执行的。

命令组

命令组list是由一个或多个管道(或命令)组成的命令序列,中间加运算符“;”、“&”、“&&”或“||”之一作为分隔符,或加“;”、“&”或换行符之一作为终止符。

在这些命令组list的运算符中,“&&”与“||”具有相同的优先级。之后是“;”与“&”,两者也具有相同的优先级。

在一个命令组list中,可以使用一个或多个换行符替代分号“;”,以分隔命令。

如果一个命令是以控制运算符“&”终止的,Shell将会以后台方式在子Shell中运行命令。Shell无须等待命令完成,即可立即返回。由分号分隔的命令是顺序执行的,Shell必须等待命令完成才能开始执行下一个命令。整个命令组list的返回值是最后一个执行的命令的结束状态。

逻辑与和逻辑或并列结构的命令组list是由一个或多个管道(或命令)组成的命令序列,中间分别加控制运算符“&&”或“||”作为分隔符。逻辑与和逻辑或并列结构的命令组list的执行是左结合的。

其中,逻辑与并列结构的命令组list具有下列语法格式:

        cmd1 && cmd2

仅当cmd1返回结束状态0时才执行cmd2

逻辑或并列结构的命令组具有下列语法格式:

        cmd1 || cmd2

仅当cmd1返回非0的结束状态时才执行cmd2

在逻辑与和逻辑或并列结构的命令组中,返回值是命令组中最后执行的一个命令的结束状态。

组合命令

        (list)                  在子Shell的环境中执行命令组list中的命令。在命令运行结束之后,影响Shell环境
                                的变量赋值与内置命令将会失效。
        {list;}                 仅在当前的Shell环境中执行命令组list中的命令。命令组list后面必须有换行符或分
                                号终止符。注意,元字符“{”、“}”与命令组list之间必须加空白字符等分隔符。
        ((expression))          按照算术运算的规则计算表达式,参见“算术计算”一节的说明。如果表达式的值不
                                是0,其结束状态为0,否则返回1。其效果等同于“let expression”命令。
        [[expression]]          根据表达式expression的计算结果返回状态代码0或1。表达式由基本的条件表达式组
                                成,参见“条件表达式”一节。在“[[”与“]]”之间,禁止执行单字的解析与文件名
                                的生成,但执行波浪号替换、参数与变量替换、算术替换、命令替换、进程替换,以
                                及删除引用符号。条件运算符(如“-f”测试)必须是未加引用的,才能被认可为基本
                                的条件表达式。
                                当与“[[”一起使用时,“<”与“>”运算符的排序依赖于当前语言环境的字符顺序。
                                当使用“==”与“!=”运算符时,运算符右边的字符串可以看作一个模式,且应按照
                                “模式匹配”一节说明的规则进行匹配。如果启用了Shell选项nocasematch(参见shopt
                                内置命令),匹配时不考虑字母的大小写。如果字符串匹配(“==”)或不匹配(“!=”)
                                模式,返回值是0,否则返回1。模式的任何部分均可加引用,强制其作为字符串进行
                                匹配。
                                附加的二进制运算符“=~”也是可用的,且与“==”和“!=”具有相同的优先级。使
                                用时,运算符“=~”右边的字符串可以看作扩展的正则表达式,因而进行相应的匹配
                                处理。如果字符串匹配模式,返回值是0,否则返回1。如果正则表达式的语法不正确,
                                条件表达式的返回值是2。如果启用了Shell选项nocasematch,匹配时不考虑字母的大
                                小写。模式的任何部分均可加引用,强制其作为字符串进行匹配。正则表达式中由圆括
                                号括住的子表达式匹配的子串保存在数组变量BASH_REMATCH中。数组
                                BASH_REMATCH索引为 0 的元素是匹配整个正则表达式的字符串部分。数组
                                BASH_REMATCH索引为n的元素是匹配第n个子表达式的子串部分。
                                使用下列运算符(按照优先级的降序列出),可以组合表达式:
                                (expr)         返回表达式expr的计算结果值。主要用于修改运算符的常规优先顺序。
                                !expr          如果表达式expr为假,计算结果为真。
                                expr1&&expr2 如果表达式expr1expr2均为真,计算结果为真。
                                expr1||expr2   如果表达式expr1expr2中的某一个为真,计算结果为真。
                                如果表达式expr1的计算结果足以确定整个条件表达式的返回值,“&&”与“||”运算
                                符不会再计算表达式expr2。
        for name[[in[words]];]do list;done
                                替换关键字in后面的words,把其中的每个元素依次赋予name变量,执行一次命令组
                                list中的命令。如果忽略了关键字in,表示对已设置的每个位置参数执行一次命令组list
                                中的命令。for命令的返回值是最后执行的一个命令的结束状态。如果关键字后面的
                                words替换后为空,则不执行任何命令。for命令返回0。
        for((expr1;expr2;expr3));do list;done
                                首先按照算术运算规则计算表达式expr1,参见“算术计算”一节的说明。然后重复地
                                计算表达式expr2,直至其值等于0。每计算一次表达式expr2,当计算结果不等于0
                                时,运行一次命令组list中的命令,并计算一次表达式expr3。如果省略了其中任何一
                                个表达式,意味着其计算结果为1。for语句的返回值是命令组list中最后一个命令的
                                结束状态。
        select name[in words];do list;done
                                替换关键字in后面的words,生成一组菜单项,在标准错误输出中依次显示每个菜单
                                项,同时在菜单项前面插入一个序号。如果忽略了关键字in,依次显示每个位置参
                                数,接着输出PS3变量的值作为提示符,然后等待从标准输入读取数据行。如果输
                                入行是一个相应于菜单项的数字,则把菜单项赋予name变量。如果输入行是空的,
                                则重新显示菜单和提示信息。如果读取的数据行是EOF,select命令结束。如果读
                                取的数据行是其他任何值,把name设置成NULL。读取的数据行保存在REPLY变
                                量中。对于每个选择,执行一次命令组list中的命令,直至执行到break命令。select
                                命令的返回值是命令组list中执行的最后一个命令的结束状态。如果未执行任何命
                                令,返回0。
        case word in[[(]pattern[|pattern]...)list;;]...esac
                                case首先解释word,然后依次尝试匹配每一个模式pattern。在考察wordpattern是
                                否匹配之前,首先对wordpattern执行波浪号替换、变量替换、算术替换、命令替
                                换、进程替换以及删除引用符号等。如果启用了Shell选项nocasematch,匹配时不考
                                虑字母大小写的差异。当发现匹配时,执行相应命令组list中的命令。如果命令组list
                                之后存在“;;”运算符,在发现第一个匹配之后立即停止其他匹配检查。如果使用“;&”
                                替代“;;”,意味着需要继续执行与下一个模式有关的命令组list中的命令。如果使用
                                “;;&”替代“;;”,表示还要继续测试下一个模式(如果存在),如果匹配成功,执
                                行相关命令组list中的命令。
        if list;then list;[elif list;then list;]...[else list;]fi
                                首先执行第一个命令组list中的命令,如果其结束状态是0,则执行关键字then后面的
                                命令组list中的命令;否则,再执行每个elif(如果存在)后面的命令组list中的命令,
                                如果其结束状态是0,执行相应then后面的命令组list中的命令;否则执行else(如果
                                存在)后面的命令组list中的命令。
        while list;do list;done
        until list;do list;done
                                只要第一个命令组list中的最后一个命令返回结束状态0,while命令就会连续地执行
                                关键字do与done之间的命令。除了采用相反的测试结果,until命令的处理逻辑与while
                                命令是等同的,即只要第一个命令组list中的最后一个命令返回非0的结束状态,until
                                命令就会连续地执行关键字do与done之间的命令。while与until语句的返回值是do
                                与done之间最后一个命令的结束状态。

Shell函数定义

Shell函数是一个命令集合体,可以像运行单个命令一样,通过引用其名字及提供的位置参数直接调用,从而执行一组命令,执行结束后返回调用者。采用下列语法格式可以声明一个Shell函数:

        [function]name()compound-cmd[redirection]

其中,定义的函数命名为namecompound-cmd是函数体,由位于花括号“{”与“}”之间的一组命令组成,其中的命令可以是任何组合命令,参见“组合命令”一节。此外,函数也可以重定向。保留字function是选用的。如果提供了保留字function,圆括号也是选用的。无论何时引用已定义的函数名,即意味着执行函数体 compound-cmd。定义函数时指定的任何重定向仅在调用函数时执行。函数的返回值是在函数体内执行的最后一个命令的结束状态。

注释

在非交互Shell中,或在启用了shopt内置命令的interactive_comments选项的交互Shell中,如果单字前面存在“#”字符或其首字符为“#”,相应的单字及同一数据行上的所有字符将被忽略。在交互Shell中,interactive_comments选项的默认设置总是启用的,如果关闭了interactive_comments选项,交互Shell也不支持注释功能。

引用

引用用于取消部分特殊字符、单字在Shell中的特殊意义,用于禁止特殊字符的特殊处理,如防止Shell识别保留字,以及防止参数替换等。

在“定义”一节列出的每一个元字符在Shell中都具有特殊的意义,如果想要表示其本身,必须加引用。

当启用了命令历史替换机制时,命令历史替换字符“!”必须加引用,以防止执行命令历史替换,除非希望如此。

bash存在3种引用方式:转义字符、单引号和双引号。

未引用的反斜线“\”是转义字符,用于维持紧随其后的下一个字符(换行符除外)的文字意义。如果出现“\换行符”形式的一对字符序列,且“\”字符本身未加引用,“\换行符”作为行延续符处理。

单引号括住的字符用于维持单引号中每个字符的文字意义。在一对单引号中不能再出现单引号,即使在单引号前加转义字符。

双引号括住的字符用于维持双引号中除“$”、“`”、“\”和“!”(如果启用了命令历史替换机制)之外的所有字符的文字意义。在双引号中,“$”和“`”保持其特殊意义,但仅当其随后的字符是“$”、“`”、“"”、“\”或换行符之一时,“\”才保持其特殊意义。如果双引号前加了转义字符,双引号本身也可以出现在双引号中。如果启用,命令历史替换可以执行,除非双引号中的“!”之前加了转义字符,此时不会删除“!”之前的转义符号。

在双引号中,特殊变量“*”与“@”仍具有特殊的意义,参见“参数(变量)”一节。

在处理“$"string"”(双引号)形式的字符串时,需按照当前的语言环境翻译string。如果当前的语言环境是C或POSIX,忽略“$”符号。如果string被翻译和替代,替换后的结果前后加双引号。

在处理“$'string'”(单引号)形式中的字符串时,其中的单字是特殊处理的。每个单字首先替换成字符串,同时使用ANSI C标准的字符编码替换其中的转义字符。替换后的结果前后加单引号,好像“$”不存在一样。如果存在,转义字符序列按照下述说明译成相应编码:

        \a        警示音。
        \b        退格符。
        \e,\E     ESC字符。
        \f        换页符。
        \n        换行符。
        \r        回车。
        \t        制表符。
        \v        纵向制表符。
        \\        反斜线。
        \'        单引号。
        \"        双引号。
        \nnn      由1~3位八进制数值nnn表示的8位编码的字符。
        \xHH      由一或两位十六进制数值HH表示的8位编码的字符。
        \cX       Ctrl-X字符。

参数(变量)

参数是Shell中的一种基本实体,用于存储数值。参数可以是一个名字、数字或“特殊参数”一节中列出的一个特殊字符。变量只是以名字表示的参数的一种。变量拥有一个数值与0个或多个属性,其属性可由declare内置命令定义。

参数或变量是在赋值的同时设置的。空串也是有效的数值。一旦设置了变量,只能使用unset内置命令予以清除。

使用下列语法格式的赋值语句,可以为变量赋值:

        name=[value]

如果未给定值value,相当于赋予变量一个空的字符串。所有的值都需要经过波浪号替换、参数与变量替换、命令替换、算术替换以及删除引用符号等处理过程。如果变量设定的属性是整数,即使没有使用“$((...))”算术替换,变量的值也是按照算术表达式计算的,参见“算术替换”一节。

赋值语句不执行单字解析,但特殊参数“$@”例外,参见“特殊参数”一节的说明。赋值语句也不执行文件名生成。赋值语句可以作为alias、declare、typeset、export、readonly与local内置命令的参数出现。

在使用赋值语句为Shell变量或数组索引赋值的上下文环境中,利用“+=”运算符可以把一个数值附加或加到变量先前的值中。对于已经设置了整数属性的变量,运算符“+=”表示按照算术表达式计算右边的值,然后把计算后的值加到变量的当前值上。对于组合赋值(“+=”)的索引数组变量而言,数组原有的元素保持不变,只是把新的值附加到数组从当前最大索引+1开始的数组元素中。对于字符串类型的变量,首先替换右边的值,把替换后的结果追加到变量值的后面。

位置参数

位置参数是由一个或多个非0数字表示的参数。位置参数是在调用命令或脚本时由Shell赋值的。也可以使用set内置命令重新赋予位置参数以新的值,但不能使用赋值语句为位置参数赋值。在调用Shell函数时,可以临时替换位置参数的值,参见“函数”一节的说明。

当位置参数由多个数字表示时,数字前后必须加花括号,参见“替换”一节的说明。

特殊参数

        Shell支持若干特殊参数,这些特殊参数只能引用,不允许人为地赋值。
        *                 $*表示从1开始的所有位置参数,每个参数是一个单独的字。单独引用时,$*相
                          当于$1、$2、$3 …,表示多个单独的参数。前后加双引号引用时,"$*"相当于
                          “$1$2$3…”,仅表示一个参数,其值是所有位置参数值的组合,中间使用IFS
                          变量定义的第一个字符(即空格)作为分隔符。如果IFS变量是NULL,参数直
                          接相连,中间没有任何分隔。
        @                 类似于$*,$@表示从 1 开始的所有位置参数,每个参数是一个单独的字。单独
                          引用时,$@相当于$1、$2、$3 …,表示多个单独的参数。前后加双引号引用
                          时,"$@"相当于"$1"、"$2"、"$3"…,每个参数都是一个单独的前后加双引号的
                          字符串。参数原封不动地传递,未做解释或替换。
        #                 $#表示位置参数(命令行参数)的数量。
        ?                 $?表示最近执行的命令或脚本的结束状态。
        -(连字符)      $-表示传递给Shell或Shell脚本的执行标志(参见set内置命令)。
        $                 $$是当前Shell的进程ID。Shell脚本经常使用$$组织临时文件名,确保文件名的
                          唯一性。
        !                 $!表示最近运行的后台进程的PID。
        0                 $0表示Shell或Shell脚本的名字。
        _(下画线)      在Shell开始运行时,$_的初始值是调用的Shell或执行的Shell脚本的绝对路径
                          名。之后,变量值是最近执行的命令的最后一个选项或参数等。当检测电子邮件
                          时,这个参数存有当前检测的邮件文件的名字。

Shell变量

下列变量是由bash自行设置的。

        BASH             调用当前bash实例的完整文件名。
        BASHOPTS         只读变量,变量值是由冒号分隔的一组启用的Shell选项,其中每一个单字都是
                         shopt内置命令“-s”选项的一个有效参数。出现在只读BASHOPTS变量中的选项
                         是内置命令输出中已经启用(on)的Shell选项。如果在启动bash时此变量已位于
                         运行环境中,在读取任何启动文件之前就会启用其中列举的每一个Shell选项。
        BASHPID          当前bash进程的进程ID。
        BASH_ALIASES     一个关联数组变量,其元素相应于由alias内置命令维护的一组内部命令别名。加
                         到这个数组的命令也将出现在命令别名表中。反之,如果清除数组元素的设置,
                         也将从命令别名表中删除相应的命令。
        BASH_ARGC        一个数组变量,其中的数值是当前bash执行时调用栈中每一组参数的数量。当前
                         子例程(Shell函数或使用“.”及source命令执行的Shell脚本)的参数数量位于
                         调用栈的最上方。当子例程开始执行时,其参数数量将赋予BASH_ARGC变量。
                         仅当处于扩展的调试模式时,Shell才会设置BASH_ARGC变量(参见shopt内
                         置命令的extdebug选项的说明)。
        BASH_ARGV        一个数组变量,其中含有当前bash执行时调用栈中的所有参数。最近一个子例程
                         调用的最后一个参数位于调用栈的最上方。当子例程开始执行时,其参数将赋予
                         BASH_ARGV变量。同样,仅当处于扩展的调试模式时,Shell才会设置
                         BASH_ARGV变量(参见shopt内置命令的extdebug选项的说明)。
        BASH_CMDS        一个关联数组变量,其元素对应于bash维护的内部命令散列表。加到这个数组的
                         命令也将出现在散列表中。反之,如果清除数组元素的设置,也将从散列表中删
                         除相应的命令。
        BASH_COMMAND     其中含有当前或即将执行的命令。
        BASH_EXECUTION_STRING
                         其中含有使用“-c”选项调用bash时的命令参数。
        BASH_LINENO      一个数组变量,其数组元素是相应于FUNCNAME数组变量每个成员的源代码文
                         件中的行号。使用LINENO变量可以获取当前的行号。
        BASH_REMATCH     一个只读数组变量,其元素0是匹配整个正则表达式的字符串部分,元素n是匹
                         配第n个加圆括号的子表达式的子串部分。
        BASH_SOURCE      一个数组变量,其数组元素是相应于FUNCNAME数组变量中的每个成员的源
                         代码文件名。
        BASH_SUBSHELL    每次调用子Shell或进入子Shell环境时,变量值加1(变量的初始值为0)。
        BASH_VERSINFO    一个只读数组变量,数组元素含有当前bash实例的版本信息。其中第0个至第5
                         个元素分别是主版本号、次版本号、修订版本号、创建版本号、发布状态及
                         MACHTYPE变量的值。
        BASH_VERSION     描述当前bash实例版本的字符串。
        DIRSTACK         一个数组变量,其中含有目录栈的当前内容。目录在栈中出现的顺序与dirs内置
                         命令输出的目录顺序相同。采用数组成员赋值的方式可以修改已经位于目录栈中
                         的目录,但只能使用pushd与popd内置命令才能增加或删除其中的目录。注意,
                         上述变量的赋值不能修改当前目录。
        EUID             在Shell启动的初始化过程中设置为当前用户的有效用户ID。这是一个只读变量。
        FUNCNAME         数组变量,其中含有当前调用栈中执行的所有Shell函数的名字,而索引0对应
                         的元素是当前执行的任何Shell函数的名字。栈中最底部的函数是“主函数”。
                         仅当执行Shell函数时,这个数组变量才会存在。这是一个只读变量,不能赋值,
                         否则将会返回一个错误信息。
        GROUPS           数组变量,其中含有当前用户从属的所有用户组。
        HISTCMD          当前命令在命令历史记录中的编号或索引。
        HOSTNAME         自动设置的当前主机的名字。
        HOSTTYPE         自动设置的字符串,用于唯一地描述bash当前运行的主机的类型。
        LINENO           每次引用这个变量时,返回一个十进制数值,表示Shell脚本或函数中当前执行
                         的命令的行号(从1开始编号)。仅当调试Shell脚本或函数时,这个变量才有
                         意义。
        MACHTYPE         自动设置的字符串,采用标准的GNU“CPU-公司-系统”格式,完整描述bash
                         当前运行系统的类型。
        OLDPWD           先前的工作目录(利用cd命令改换到当前目录之前所在的工作目录)。
        OPTARG           getopts命令已处理的前一个选项参数的值。
        OPTIND           getopts命令需要处理的下一个选项参数的索引。
        OSTYPE           自动设置的、描述bash当前运行系统的操作系统的字符串。
        PIPESTATUS       一个数组变量,其中含有一组最近执行的前台管道进程的结束状态。
        PPID             父进程的进程ID(只读变量)。
        PWD              表示当前工作目录,由cd命令设置,其变量值等同于pwd命令的输出。
        RANDOM           每次引用这个变量时,即可生成一个均匀分布于0~32767范围内的随机整数。
                         如果赋予RANDOM变量一个数值,可以达到初始化随机数序列的目的。
        REPLY            当使用read命令读取输入数据时,如果没有指定变量参数,可以把REPLY变量
                         用作read命令的默认变量,从而把read命令读取的输入数据赋予REPLY变量。
        SECONDS          每当引用这个变量时,返回bash自调用迄今运行的时间(秒数)。如果赋予
                         SECONDS变量某个值,之后再引用这个变量时的返回值是赋值后的时间(秒数)
                         加上赋予SECONDS变量的值。
        SHELLOPTS        只读变量,其变量值是由冒号分隔的一组启用的Shell选项,也是“set -o”命令
                         的输出结果。每个单字均可作为“set-o”命令的一个有效选项参数。在启动bash
                         时,如果这个变量存在于环境中,在读取任何启动文件之前,变量值中的每个Shell
                         选项将被启用。
        SHLVL            每当启动一个bash实例,这个变量的值都会加1。
        UID              在Shell启动的初始化过程中设置为当前用户的用户ID。这是一个只读变量。
        下述变量是Shell在运行期间使用的变量。在某些情况下,bash会赋予变量一个默认值,详见每个变量
的说明。
        BASH_ENV         当调用非交互的bash运行Shell脚本时,如果此变量已经设置,将会使用变量值
                         指定的绝对路径文件名,作为~/.bashrc初始化文件执行之。bash采取与点“.”
                         或source命令类似的方法解释执行BASH_ENV变量指定的文件,即在当前环境
                         中执行其中的命令。此外,BASH_ENV变量指定的文件只需具有可读访问权限
                         即可,不必是可执行文件。但与使用点“.”或source命令不同的是,出于安全
                         的考虑,bash不会使用PATH变量检索BASH_ENV变量指定的命令文件。在解
                         释BASH_ENV变量值之前,首先需要执行变量替换、命令替换及算术替换等。
        CDPATH           定义cd命令的检索路径,其变量值是一组由冒号分隔的目录。如果cd命令中指
                         定的目的目录为相对路径名,cd命令首先会在当前目录中搜寻目的目录。如果
                         未发现目的目录,检索CDPATH变量中列举的每一个路径名,直至找到目的目
                         录,并成功地改换工作目录。如果最终仍未发现目的目录,则保持当前工作目
                         录不变。例如,假定把此变量设置为/home/gqxing,其中存在两个子目录bin和
                         src。如果用户当前位于/home/gqxing/bin目录中,输入“cd src”命令后,即使没
                         有指定全路径名,仍可把工作目录改换到/home/gqxing/src中。
        BASH_XTRACEFD    如果设置的整数是一个有效的文件描述符,当使用“set-x”命令启用了跟踪功能
                         时,bash将会把生成的跟踪信息写到指定文件描述符表示的文件中。当清除
                         BASH_XTRACEFD变量的设置或赋予一个新值时,关闭相应的文件描述符。清
                         除BASH_XTRACEFD变量的设置或赋予一个空串时,将会把跟踪的输出信息写
                         到标准错误输出。注意,如果把BASH_XTRACEFD变量设置成2(标准错误输
                         出的文件描述符),然后清除该变量的设置将会导致标准错误输出的关闭。
        COLUMNS          用于定义终端窗口的列宽。select内置命令使用这个变量的值确定终端窗口的数
                         据显示宽度,以便输出菜单选项列表。此变量值也用于确定Shell编辑窗口的列
                         数。在收到SIGWINCH信号之后Shell会自动设置。
        FCEDIT           用于设定fc内置命令使用的默认编辑器,以便用户能够使用熟悉的编辑器编辑
                         命令行。此外,crontab等命令也使用这个变量的值确定应调用哪一个编辑器。
        FIGNORE          其值是由冒号“:”分隔的一组文件名后缀,表示在执行文件名补缺时应忽略的文
                         件扩展名。当文件名的扩展名匹配FIGNORE变量的定义时,从匹配的文件名列
                         表中排除之,例如,“.o:~”表示在文件名补缺时忽略其后缀为“.o”或“~”
                         的文件。
        GLOBIGNORE       其值是由冒号分隔的一组模式,用于定义生成文件名时应忽略的一组文件名。如
                         果匹配文件名模式的文件名也匹配变量值中的某个模式,则从匹配的文件名中删
                         除之。
        HISTCONTROL      其值是由冒号分隔的一组关键字,用于控制如何保留命令历史记录中的命令。如
                         果其中含有关键字ignorespace,意味着不保留命令行首字符为空格的命令。关键
                         字ignoredups表示不保留命令行匹配先前历史记录的命令。关键字ignoreboth是
                         ignorespace与ignoredups的统称。关键字erasedups表示在保存当前命令之前,应
                         首先从命令历史记录中删除先前的匹配当前命令行的所有命令。如果清除了
                         HISTCONTROL变量的设置,或其中不包括有效的关键字,Shell将会在历史记
                         录中保存其读取的且满足HISTIGNORE变量定义原则的所有命令。
        HISTFILE         指定存储命令历史记录的文件,默认的文件是~/.bash_history。如果使用unset
                         内置命令清除此变量,在运行交互Shell时不会保存命令历史记录。
        HISTFILESIZE     用于设定命令历史文件能够保存的最大命令行记录的数量,默认值为 500(条命
                         令)。
        HISTIGNORE       其值是由冒号分隔的一组模式,用于确定应在命令历史记录中保存哪些命令。每
                         个模式都需要从行首开始整行匹配。按照HISTCONTROL变量指定的原则检测
                         之后,再使用HISTIGNORE变量定义的每个模式对命令行进行过滤测试。
        HISTSIZE         用于设定命令历史缓冲区中能够保存的最大命令记录数量,默认值为500(条命令)。
        HISTTIMEFORMAT   如果设置了此变量,且其值非空,变量的值用作格式字符串,当使用history内置
                         命令显示命令历史时,显示每个命令记录的时间信息。如果设置了此变量,时间
                         信息(使用历史注释字符以区别于时间与命令)也会写到命令历史文件,故可以
                         在Shell会话之间予以维持。
        HOME             当前用户的主目录,也是cd内置命令的默认参数。波浪号替换时也使用这个变
                         量的值。
        HOSTFILE         其变量值是一个与/etc/hosts文件格式相同的文件的名字,其中含有当前主机的名
                         字,以备Shell在需要补充主机名时使用。如果设置了变量HOSTFILE,但其值为空,
                         或指定的文件不可读,bash将尝试读取/etc/hosts文件,以获得可用的主机名。
        IFS              用于定义内部字段分隔符,其默认值为空格、制表符和换行符。字段分隔符通
                         常用于分解单字,把命令行或字符串分解成最基本的构成元素。IFS变量值中的
                         第一个字符用于解析特殊变量“$*”中的位置参数。
        IGNOREEOF        控制交互Shell在仅仅收到EOF字符时应采取的处理动作。如果设置了此变量,
                         其值是在退出bash之前必须在作为第一个字符的输入行上连续输入的EOF字符
                         的数量。如果变量存在,但变量的值并非数字值,或没有赋予任何值,其默认值
                         为10。如果变量不存在,EOF表示对Shell的输入结束。
        INPUTRC          用于设定readline启动文件的文件名,以取代默认值~/.inputrc。
        LANG             用于设置本地语言环境。补充设置LC_*系列变量未明确定义的本地语言环境。
        LC_ALL           用于统一、强制设置LANG与LC_*系列变量的值。
        LC_COLLATE       用于定义本地语言环境(尤其是模式匹配时)使用的字符集排序规则、范围表达
                         式以及等价类等。
        LC_CTYPE         用于确定系统怎样处理各种语言环境的字符集,包括字符的分类,字母的大小
                         写转换规则,以及其他字符属性。这个变量确定了在文件名生成与模式匹配中
                         如何解释字符以及字符的分类。
        LC_MESSAGES      用于定义各种实用程序使用的肯定与否定响应的格式与内容。
        LC_NUMERIC       用于确定本地语言中小数点与千分数等的表示方式和显示格式。
        LINES            用于定义终端窗口的行数。select内置命令使用此变量的值确定终端窗口的数据
                         显示行数,以便输出菜单选项列表。变量值也可用于确定Shell编辑窗口的行数。
                         在收到SIGWINCH信号之后Shell会自动设置。
        MAIL             用于定义用户邮箱的路径文件名。如果此变量设置成一个文件名,且未设置
                         MAILPATH变量,bash将会根据指定的文件通知用户是否有新邮件到达。
        MAILCHECK        指定Shell检测邮件的频度(以秒为单位),默认值为60秒。如果未设置此变量,
                         或把变量设置成一个小于0的数值,Shell将会停止检测邮件。
        MAILPATH         一组由冒号分隔的文件名与提示信息(中间加问号“?”分隔符),供系统检查
                         是否有新到的邮件。当新邮件到达指定的文件时显示指定的信息提示用户。在提
                         示信息中,“$_”表示当前的邮件文件。例如,MAILPATH='/var/mail/user?"You
                         have mail":~/shell-mail?"$_has mail!"'。
        OPTERR           如果设置为1,bash将会显示getopts命令生成的错误信息。每次调用Shell或执
                         行Shell脚本时,都会把OPTERR初始化为1。
        PATH             用于定义命令的检索路径及顺序,其变量值由冒号“:”分隔的目录组成。由相邻
                         的两个冒号、初始或行尾的单个冒号定义的空目录表示当前工作目录。普通用户
                         的命令检索路径通常包括/bin和/usr/bin等目录,超级用户的命令检索路径通常包
                         括/sbin、/bin、/usr/sbin和/usr/bin等目录。当用户输入命令时,Shell将会根据
                         PATH变量列举的目录及顺序,从中检索并执行匹配的可执行程序。如果提交的
                         命令其目录不在检索路径中,必须输入命令的完整路径名才能执行。当检索路
                         径中的不同目录存在同名的命令时,Shell将会使用第一个发现的命令。
        POSIXLY_CORRECT当bash开始运行时,如果设置了这个环境变量,Shell在读取启动文件之前将会
                         进入POSIX模式,好像在运行bash时指定了“--posix”选项。如果在bash运行期间
                         设置了这个环境变量,bash将会启用POSIX模式,好像执行了“set-o posix”命令。
        PROMPT_COMMAND
                         如果设置了这个变量,在每次显示主命令提示符之前,以此变量的值作为命令执
                         行一次。
        PROMPT_DIRTRIM   如果设置成一个大于0的数字,在扩展提示符中的“\w”与“\W”转义字符时,
                         变量值用作目录保留部分(从右开始)的字符数量,参见“提示符”一节。删除
                         的字符使用省略号代替。
        PS1              第一级命令提示符,或主命令提示符(简称主提示符)。变量的默认值为
                         “'[\u@\h \W]\$ '”,其中“\$”表示普通用户的命令提示符为“$”,超级用户
                         的命令提示符为“#”。
        PS2              第二级命令提示符,默认值为大于号“>”。如果输入的命令不完整,或需要用
                         户提供附加的数据时,系统将会按此变量的设置提示用户继续输入。
        PS3              第三级命令提示符,其默认值为“#?”。这个变量主要用于设置select命令的菜
                         单选择提示符。
        PS4              第四级命令提示符,其默认值为加号“+”。这个变量主要用作Shell脚本的调试
                         标志符,在跟踪脚本执行的过程中,Shell将会在显示其执行的每一个命令之
                         前,首先输出这个变量定义的值。必要时,变量值的第一个字符可以重复多次,
                         以表示重定向的层次。
        SHELL            定义Shell命令文件的完整路径名。在Shell启动时,如果未设置此变量,bash
                         将会把当前用户注册Shell的完整路径名赋予这个变量。注意,vim等工具使用这
                         个变量值作为默认的Shell。
        TMOUT            用于定义用户与系统会话过程的超时值。在交互Shell中,TMOUT变量的值可
                         以解释为在输出命令提示符之后等待用户输入的时间(单位秒)。在输出命令提
                         示符之后,如果在TMOUT规定的时间之内未输入任何命令,Shell将会因超时
                         而终止执行,导致系统关闭用户的终端窗口,或断开用户的终端连接。对于read
                         内置命令而言,如果TMOUT变量的值大于0,这个数值可以用作read命令默认
                         的超时值。对于select内置命令而言,如果在TMOUT规定的时间之内一直没有
                         收到键盘输入数据,select命令将会终止执行。
        TMPDIR           定义Shell创建临时文件时使用的临时目录名。

数组

bash支持一维的索引数组与关联数组(变量)。任何变量均可用作索引数组变量。使用declare内置命令能够明显地声明一个数组。对于数组元素而言,没有最大的容量限制,也不要求数组元素的索引或赋值是连续的。索引数组使用整数(包括算术表达式)下标引用,从0开始索引。关联数组可以使用任何字符串引用。

对于任何变量name,如果采用“name[subscript]=value”形式的语法格式赋值,将会自动创建一个索引数组。数组的下标按算术表达式的方式处理,其计算结果必须是大于或等于0的数值。若想明显地声明一个索引数组,可以使用“declare-a name”内置命令。也可写成“declare-a name[subscript]”形式,但下标将被忽略。

使用“declare-A name”命令可以创建一个关联数组。

可以使用declare与readonly内置命令指定数组变量的属性。指定的数组变量属性适用于数组的所有成员。

使用“name=(value1 value2... valueN)”形式的组合赋值语句可以为整个数组赋值,其中每个值具有“[subscript]=string”的形式。索引数组赋值使用方括号与下标。为索引数组赋值时,如果提供了选用的方括号与下标,表示仅赋值指定索引的数组元素,否则,赋值数组元素的索引是最近一个赋值语句引用的数组元素的索引加1。索引数组的下标从0开始。

为关联数组赋值时必须指定下标。

上述语法格式也适用于declare内置命令。使用上方说明的“name[subscript]=value”语法格式也可以为单个数组元素赋值。

采用语法格式“${name[subscript]}”可以引用任何数组元素。其中,使用花括号的主要目的是为了避免与文件名生成产生冲突。如果subscript是“@”或“*”,表示数组name的所有元素。仅当出现在双引号中时,上述两个下标表达的意义才有所不同。如果“${name[*]}”前后增加了双引号,替换结果是一个单字,其值是并列每个数组元素,中间加IFS变量值的第一个字符定义的分隔符。如果“${name[@]}”前后增加了双引号,替换结果是由每个数组元素构成的多个单字。“${#name[subscript]}”替换结果是“${name[subscript]}”的长度。如果其下标是“*”或“@”,替换结果是数组元素的数量。引用数组变量而不加下标等价于使用0作为下标引用整个数组。

如果赋予下标一个值,可以认为数组变量已经设置。空串是一个合法的值。

unset内置命令用于销毁数组,而“unset name[subscript]”命令用于销毁指定下标索引的数组元素。“unset name”命令(其中name是一个数组)或“unset name[subscript]”命令(subscript是“*”或“@”)将会删除整个数组。

declare、local和readonly内置命令均支持指定索引数组的“-a”选项,以及指定关联数组的“-A”选项。read内置命令采用“-a”选项,把读自标准输入的一组数据赋予指定的数组。set和declare内置命令能够采用一种可用于重新赋值的方式显示数组的值。

替换

把命令行解析成一系列单字之后,再从左到右依次执行花括号替换、波浪号替换、参数与变量替换、算术替换、命令替换、单字解析以及文件名生成等各种替换操作。

取决于系统是否支持,另外一个可用的附加替换是进程替换。

注意,只有花括号扩展、单字解析和文件名生成能够改变原有单字的数量。其他的替换只是把一个单字替换成另外一个单字。唯一的例外是“$@”与“${name[@]}”替换,参见“参数(变量)”一节的说明。

花括号扩展

利用花括号扩展,能够生成任意的字符串。这一扩展机制类似于文件名生成,但生成的文件名不必一定存在。在花括号扩展的情况下,模式前可以存在一个选用的字符串前缀, 然后是一系列由逗号分隔的字符串或序列表达式,位于左右花括号之间,之后还可以附加一个选用的字符串后缀。扩展时把前缀字符串加到花括号中的每个字符串之前,然后再把后缀字符串附加到新组合的每个字符串之后,从左到右依次扩展。

花括号扩展可以嵌套。扩展后的每个字符串并不排序,仍保持从左到右的列举顺序不变。例如,“a{d,c,b}e”能够扩展为“ade ace abe”。

序列表达式采用“{x..y[..incr]}”形式的语法格式,其中,xy或者是一个整数,或者是单个字符,incr是一个选用的整数增量。如果xy是一个整数,表达式可以扩展到xy之间的每一个整数,包括xy本身。整数之前可以加前缀0,确保每一项具有相同的宽度。在此情况下,Shell试图强制生成的所有项都具有相同数量的数字。不足者前面加0。如果xy是字符,表达式可以扩展到字符顺序xy之间的每一个字符,包括xy本身。如果指定了整数增量,增量用作每一项的选取间隔。默认的增量是1或-1。

花括号扩展是在其他任何替换之前首先执行的,而且是严格按文字处理的,因此,扩展结果中会保留其他替换中能够解释的任何特殊字符。对扩展结果或花括号之间的文字,bash不做任何语法解释处理。

在花括号扩展的语法格式中,必须包含未引用的左右花括号,以及至少一个未引用的逗号或合法的序列表达式。如果书写不正确,花括号扩展不会执行。如果需要在花括号中使用非语法意义的“{”或“,”字符文字本身,可以在前面增加转义符号。为避免与参数替换产生冲突,bash不支持字符串“${”形式的花括号扩展。

花括号扩展通常主要用于简化具有共同字符串前缀的路径名,以较短的书写形式生成多个文件名。例如:

        mkdir /usr/local/src/bash/{old,new,dist,bugs}

        chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}

bash的花括号扩展与传统的sh并不兼容。sh不会特别解释和处理单字中的花括号,而是在输出中保持原样不变,但bash会执行花括号扩展,最后删除花括号。例如,在sh中引入单字“file{1,2}”,其输出结果是等同的。而在bash中,同一单字扩展后的输出是file1和file2。如果需要与sh严格兼容,可以使用“+B”选项启动bash,或使用set命令的“+B”选项禁用花括号扩展。

波浪号替换

如果某个单字前面存在一个未加引用的波浪号“~”,单字中的所有字符(如果其中不存在未加引用的斜线字符)或第一个未加引用的斜线字符前面的所有字符可以看作一个波浪号前缀。如果波浪号前缀中的任何字符均未加引用,紧随波浪号的字符串通常作为一个注册用户名处理(如“~gqxing/…”)。如果波浪号前缀是一个空串(如单独的“~”或“~/”),则使用HOME变量值替换波浪号。如果HOME变量未设置,则使用当前Shell用户的主目录替换波浪号。否则,使用指定注册用户名的主目录替换波浪号前缀。

如果波浪号前缀是“~+”,使用PWD的变量值替换波浪号前缀。如果波浪号前缀是“~-”,使用OLDPWD(如果已经设置)的变量值替换波浪号前缀。如果紧随波浪号的字符是一个数字n,数字前面存在一个选用的“+”或“-”号字符,使用目录栈中的相应目录替换波浪号前缀,替换的结果与使用“dirs +n”或“dirs -n”内置命令的输出效果相同。如果紧随波浪号的只是一个数字n,而没有“+”或“-”号前缀,默认的前缀是“+”。

如果注册用户名不存在,或者波浪号替换失败,则波浪号前缀保持不变。

对于“:”或第一个“=”之后的每个变量赋值,Shell都会立即检查是否存在未加引用的波浪号前缀,执行波浪号替换。因此,在PATH、MAILPATH和CDPATH等Shell变量的赋值语句中,可以使用目录或文件名与波浪号的组合,赋予可替换的值。

参数(变量)替换

如同“参数(变量)”一节所述,变量也是参数,即命名的参数。因此,参数替换也是常规的变量替换。

美元符号“$”可用于执行参数替换、命令替换或算术替换。参数名(包括变量名)前后可以加花括号,以确保参数的替换不会产生歧义。

当选用花括号时,匹配的结束花括号“}”之前不能加转义符号“\”,不能位于引号之内,也不能位于嵌套的算术替换表达式、命令替换或参数替换表达式中。

        ${parameter}
            使用变量值进行替换。同$parameter一样,表示引用变量的值,或使用变量的值进行替换。在某
            些情况下,只有采用${parameter}引用形式,其意义才是比较明确的。当parameter是一个位置参
            数,且其数字大于9时,或parameter后面附有其他字符,而这些字符并非parameter名字的一部
            分时,花括号必须存在。例如,在定义PATH变量时,如果需要连接字符串变量,
            PATH=${PATH}:/opt/bin比PATH=$PATH:/opt/bin更容易阅读和理解。如果parameter变量的第
            一个字符是感叹号“!”(紧随左花括号之后),表示变量的间接引用。bash使用parameter的其
            余部分作为变量,使用该变量的值作为新的变量名,然后使用新变量的值进行替换,而不是使用
            parameter变量的值进行替换。但下面介绍的${!prefix*}与${!name[@]}例外。
        ${parameter:-word}
            使用默认值补缺。如果parameter变量未设置或为NULL,使用word作为变量的值进行变量替换。
            否则,使用变量的值进行变量替换,变量的值保持不变。注意,在替换之前,首先应对 word 进
            行波浪号替换、参数替换、命令替换与算术替换,下同。
        ${parameter:=word}
            使用默认值赋值。如果parameter变量未设置或为NULL,则把word赋予变量同时执行变量替
            换。注意,不能采用这种方式为位置变量或其他特殊变量赋值。
        ${parameter:?word}
            引用未定义的变量报错。如果parameter变量未设置或为NULL,显示错误信息。如果变量未设
            置或为NULL,使用word作为错误提示信息,写到标准错误输出。如果省略了word,输出默认
            的错误信息,表示变量未设置。在非交互方式,如运行Shell脚本时,终止脚本的执行,返回一个
            非0的结束状态(交互式Shell会话例外)。如果变量已经设置,使用变量值进行变量替换。
        ${parameter:+word}
            使用替代值。如果parameter变量未设置或为NULL,使用NULL进行变量替换(即不做变量替
            换)如果变量已经设置,使用word进行变量替换,但变量的值保持不变。
        ${parameter:offset}
        ${parameter:offset:length}
            抽取子串。从parameter变量值的字符偏移值offset开始,截取指定长度length的子串,如果省略
            了长度length,从偏移值offset开始截取整个子串。lengthoffset是算术表达式,参见“算术计
            算”一节。length的计算结果必须是一个大于等于0的整数。如果offset的计算结果小于0,表示
            偏移值是从parameter结尾开始反向计算的(负号与前面的冒号之间必须插入至少1个空格,以
            免与第二个参数替换形式“:-”混淆)。如果parameter是@,最终结果是从offset开始的指定个
            数length的位置参数。注意,位置参数的偏移值是从1开始计算的。如果parameter是一个使用
            “@”或“*”作为下标的索引数组名,最终结果是从${parameter[offset]}开始的指定数量 length
            的数组元素。负的偏移值offset表示从索引数组的最大下标开始反向计算。注意,数组下标的偏
            移值是从0开始计算的。
        ${!prefix*}
        ${!prefix@}
            显示匹配前缀的变量。选择名字起始部分匹配指定前缀prefix的所有变量,每个变量之间采用IFS
            特殊变量值的第一个字符作为分隔符。当采用第二种形式(即使用“@”)且前后加双引号时,
            每个变量名是一个单独的字。
        ${!array[@]}
        ${!array[*]}
            显示每个数组元素的下标。如果 array 是一个数组变量,显示每个数组元素的下标。如果 array
            不是数组变量,且array已经设置,其结果为0,否则结果为NULL。当采用第一种形式(即使用
            “@”),且前后加双引号时,每个下标是一个单独的字。
        ${#parameter}
            计算变量值的长度。使用parameter变量值的字符数量进行变量替换。如果parameter是“*”或
            “@”,“${#*}”或“${#@}”参数替换的结果是位置参数的数量。如果parameter是一个数组
            array,“${#array}”表示数组中第一个元素的长度,“${#array[*]}”或“${#array[@]}”表示数
            组元素的个数。
        ${parameter#word}
        ${parameter##word}
            删除变量值前缀。删除parameter变量值前部匹配给定模式word的最短(一个“#”)或最长(两
            个“#”)部分的子串。如果应用于文件路径名,${parameter##word}替换的效果相当于运行
            basename命令。如果parameter是“*”或“@”,上述模式匹配与删除操作依次施加于所有的位
            置参数。如果parameter是一个使用“*”或“@”作为下标的数组array,“${array[*]#word}”
            或“${array[@]##word}”的模式匹配与删除操作施加于每一个数组元素。
        ${parameter%word}
        ${parameter%%word}
            删除变量值后缀。删除parameter变量值后部匹配给定模式word的最短(一个“%”)或最长(两
            个“%”)部分的子串。如果应用于文件路径名,${parameter%word}可用于抽取路径名的目录部
            分。如果parameter是“*”或“@”,上述模式匹配与删除操作依次施加于所有的位置参数。如
            果 parameter 是一个使用“*”或“@”作为下标的数组 array,“${array[*]%word}”或
            “${array[@]%% word}”的模式匹配与删除操作施加于每一个数组元素。
        ${parameter/pattern/string}
            模式替换。使用string替换parameter变量中匹配模式pattern的最长子串。如果模式的首字符是
            “/”,使用string替换匹配模式的所有子串(通常仅替换第一个匹配模式的子串)。如果模式的
            首字符是“#”,必须从parameter变量的起始位置开始匹配。如果模式的首字符是“%”,必须
            对parameter变量的后尾部分进行匹配。如果string是一个空串,删除匹配模式的所有子串,此时,
            模式后面的斜线字符“/”可以忽略。如果parameter是“@”或“*”,依次替换匹配的每一个位
            置参数。如果parameter是一个使用“@”或“*”作为下标的数组变量,依次替换每一个匹配的
            数组元素。
        ${parameter^pattern}
        ${parameter^^pattern}
        ${parameter,pattern}
        ${parameter,,pattern}
            转换变量值的大小写字母。运算符“^”表示把匹配指定模式pattern的部分parameter变量值的小
            写字母转换成大写字母。“,”表示把匹配指定模式的部分parameter变量值的大写字母转换成小
            写字母。“^^”和“,,”表示转换匹配指定模式的每个字母的大小写。“^”与“,”表示仅转换匹
            配指定模式的第一个字母的大小写。如果省略了模式,默认的模式是“?”,表示匹配每一个字符。
            如果 parameter 是“@”或“*”,依次修改每个位置参数中匹配给定模式的大小写字母。如果
            parameter是一个使用“@”或“*”作为下标的数组变量,则依次修改每一个数组元素中匹配给
            定模式的大小写字母。

命令替换

命令替换意味着使用命令的输出替换命令本身。命令替换可以采用下列两种形式之一:

        $(command)

        `command`

在执行命令替换时,bash首先执行命令,然后使用命令的标准输出(删除最后的换行符)替换命令的位置。嵌套的换行符不会在命令替换过程中删除,但可在单字解析期间删除。作为一种特例,如果命令替换是“$(cat file)”,可以使用等价的但更快的“$(<file)”取而代之。

当采用第二种命令替换形式时,“\”保持其文字意义,除非后面跟有“$”、“`”或“\”。当采用第一种命令替换形式“$(command)”时,圆括号中的所有字符均作为命令的组成部分处理。

命令替换可以嵌套。采用第二种命令替换形式时,嵌套时需要在内部的反向单引号“`”之前加转义符号。

如果替换在双引号中出现,替换的结果不执行单字解析与文件名生成。

算术替换

算术替换用于计算算术表达式,使用计算结果替换其位置。算术替换的语法格式如下:

        $((expression))

表达式的处理如同双引号的处理,但圆括号中的双引号并不做特殊处理。表达式中的所有元素都需执行参数与变量替换、命令替换及删除引用符号。算术表达式可以嵌套。

算术表达式的计算遵循“算术计算”一节介绍的规则。如果表达式不符合要求,bash将会输出一条错误信息,而且也不会产生替换。

进程替换

在支持命名的管道或/dev/fd/n形式的打开文件的系统中,bash也支持进程替换。进程替换采用“<(list)”与“>(list)”形式的语法格式。进程list运行时,其标准输入或输出连接到一个管道或/dev/fd目录中的某个文件。作为参数,把文件名传递给当前命令。如果采用“>(list)”形式的进程替换,写到文件的数据将作为进程list的输入。如果采用“<(list)”形式的进程替换,可通过读取文件参数获取进程list的输出。

如果存在,进程替换可与参数和变量替换、命令替换以及算术替换同时执行。

单字解析

在参数与变量替换、命令替换以及算术替换之后,Shell还要对位于双引号之外的结果进行扫描,解析其中的单字,解析成Shell能够处理基本元素。

Shell把IFS变量值的每一个字符作为分隔符处理,根据这些字符把各种替换的结果解析成单字。如果未设置IFS,或其值是默认的空格、制表符与换行符,忽略替换结果起始或结尾部分的空格、制表符或换行符序列。替换结果中其他位置的空格、制表符或换行符序列用于分解单字。如果IFS的变量值不同于默认值,忽略单字前后的空格、制表符以及IFS定义的其他字符序列。IFS中非空白字符的其他任何字符,以及邻近的任何IFS空白字符用作字段分隔符。IFS的空白字符序列也作为分隔符处理。如果IFS变量的值为空,则不执行单字解析。

在单字解析过程中,显式出现的空参数“""”(两对双引号)或“''”(一对单引号)仍然保持不变。参数与变量替换后生成的、未加引用的空参数被删除。但是,如果替换后生成的空参数位于双引号中,这样的空参数仍然保持。

如果没有执行任何替换,也不执行单字解析。

文件名生成

除非指定或设置了“-f”选项,在完成单字解析之后,bash开始扫描每一个单字,检测其中是否存在“*”、“?”或“[”字符。如果存在,假定这是一个文件名模式,使用匹配模式的、按照字符顺序排序的一组文件名替换单字。如果未发现匹配的文件名,且Shell选项nullglob也未启用,单字保持不变。如果使用shopt内置命令设置了nullglob选项,且不存在匹配的文件名,则删除单字。如果设置了Shell选项failglob,且未发现匹配的文件名,则输出一条错误信息,不执行相应的命令。如果启用了Shell选项nocaseglob,匹配时不考虑字母的大小写。当一个模式用作文件名生成时,除非设置了Shell选项dotglob,首字符为句点“.”或“.”后跟有一个斜线“/”字符的文件名必须显式匹配。在匹配路径名时,必须总是明确给出其中的斜线字符“/”。在其他情况下,不会特别处理“.”字符。

GLOBIGNORE变量可用于限定一组匹配模式的文件名。如果设置了此变量,且匹配文件名模式的文件也匹配GLOBIGNORE变量定义的任何模式,需要从匹配结果中删除这样的文件名。当设置了GLOBIGNORE变量且不为空时,总是忽略“.”与“..”文件。而且,把GLOBIGNORE变量设置成非空值也具有启用Shell选项dotglob的效果,故可以匹配首字符为“.”的隐藏文件名。若想恢复传统的忽略文件名首字符“.”的文件处理方式,可在变量中增加一个“.*”模式。清除GLOBIGNORE变量时,也将禁用dotglob选项。

模式匹配

除了下面列举的特殊字符,其他任何字符(编码为0的NULL字符除外)也可以出现在模式中,这些普通字符能够匹配其本身。在特殊字符前增加转义符号“/”,可以取消其特殊意义。两个相邻的转义符号表示转义符号本身。如果需要匹配特殊字符本身,特殊字符前必须加转义符号等引用符号。

        用于模式匹配的特殊字符具有下列意义:
        *          匹配任何字符串,包括空串。在启用了Shell选项globstar时(参见shopt内置命令),“*”
                   用作文件名生成,两个相邻的“**”用作单个模式,能够匹配所有的文件,包括0个或多个
                   目录与子目录。如果后面跟随的是一个“/”,两个相邻的“**”只能匹配目录与子目录。
        ?          匹配任何一个字符。
        [...]      匹配方括号中枚举的任何一个字符。如果两个字符之间存在一个连字符“-”,表示一个字
                   符范围表达式,能够匹配当前语言环境字符集中其排序位于这两个字符(包括本身)之间的
                   任何一个字符。如果“[”之后的第一个字符是“!”或“^”,意味着匹配其表示范围之外的
                   任何字符。范围表达式中的字符排序顺序是由当前语言环境和Shell变量LC_COLLATE(如
                   果已经设置)的值确定的。若想匹配连字符“-”本身,可以把“-”放在方括号中的第一个
                   或最后一个字符位置。若想匹配“]”,可以把“]”放在方括号中的第一个字符位置。
                   在方括号中,可以使用“[:class:]”的形式指定字符类,其中class是POSIX标准定义的字符
                   类alnum、alpha、ascii、blank、cntrl、digit、graph、lower、print、punct、space、upper、word
                   或xdigit之一。字符类用于匹配字符类中的任何字符,例如,字符类word表示能够匹配任
                   何字母、数字和下画线字符“_”。

如果使用内置命令shopt启用Shell选项extglob,bash也支持若干扩充的模式匹配运算符。在下列说明中,pattern-list是由一个或多个模式、中间加“|”分隔符构成的组合模式。把下列一个或多个模式并列在一起还可以形成更复杂的组合模式:

        ?(pattern-list)       匹配0个或1个给定的模式。
        *(pattern-list)       匹配0个或多个给定的模式。
        +(pattern-list)       匹配1个或多个给定的模式。
        @(pattern-list)       匹配1个给定的模式。
        !(pattern-list)       除了给定的1个模式之外,匹配任何字符串。

删除引用符号

在完成前述的所有替换之后,删除未加引用的且并非替换结果的“\”、“'”与“"”等引用符号。

I/O重定向

在执行命令之前,可以使用Shell支持的特殊记号重新定向命令的标准输入、标准输出和标准错误输出。也可以利用I/O重定向打开或关闭当前Shell执行环境中的文件。重定向符号可以出现在简单命令的任何位置,如简单命令的前面或后面等。重定向的处理是按其出现的顺序,从左到右依次处理的。

每个重定向符号之前可以加一个表示文件描述符的数字或“{varname}”形式的变量。在此情况下,除了“>&-”与“<&-”之外,对于每一个重定向符号,Shell都会分配一个大于10的文件描述符,赋予varname变量。如果“{varname}”位于“>&-”或“<&-”之前,表示关闭varname变量值定义的文件描述符。

在下列说明中,如果省略了文件描述符,重定向符号的第一个字符是“<”,重定向引用的是标准输入(文件描述符0)。如果重定向符号的第一个字符是“>”,则重定向引用的是标准输出(文件描述符1)。

在下列叙述中,除非特别说明,紧随重定向符号的单字需经历花括号扩展、波浪号替换、参数与变量替换、命令替换、算术替换、删除引用符号、文件名生成以及单字解析。如果替换成多个单字,bash将会输出一条错误信息。

注意,I/O重定向的顺序是非常重要的。例如,“ls > filelist 2>&1”命令表示把标准输出和标准错误输出均重定向到文件filelist,而“ls 2>&1 > filelist”命令表示将标准输出重定向到文件filelist,把标准错误输出重定向到标准输出。

在I/O重定向中,bash支持下列特殊文件:

        /dev/fd/fd            如果fd是一个合法的整数,重定向到文件描述符fd对应的文件。
        /dev/stdin            重定向到文件描述符0(标准输入)。
        /dev/stdout           重定向到文件描述符1(标准输出)。
        /dev/stderr           重定向到文件描述符2(标准错误输出)。
        /dev/tcp/host/port    如果host是一个有效的主机名或IP地址,且port是一个整数端口号或服务名,
                              bash将会尝试打开一个相应套接字的TCP连接。
        /dev/udp/host/port    如果host是一个有效的主机名或IP地址,且port是一个整数端口号或服务名,
                              bash将会尝试打开一个相应套接字的UDP连接。

打开或创建文件失败将会导致重定向失败。使用大于9的文件描述符执行重定向需要小心,因为这有可能与Shell内部使用的文件描述符冲突。

输入重定向

输入重定向表示以读的方式打开指定的文件(文件名是单字替换后的结果)作为文件描述符n。如果未指定n,默认的文件描述符是0,即打开指定的文件作为标准输入。

输入重定向的一般语法格式如下:

        [n]<word

输出重定向

输出重定向表示以写的方式打开指定的文件(文件名是单字替换后的结果)作为文件描述符n。如果未指定n,默认的文件描述符是1,即打开指定的文件作为标准输出。如果文件不存在,创建新的文件。如果文件存在,清除现有文件中的内容。

输出重定向的一般语法格式如下:

        [n]>word

如果重定向符号是“>”,且set内置命令的noclobber选项已经启用,当指定的文件存在且是一个普通文件时,重定向将会失败。如果重定向符号是“>|”,或重定向符号是“>”,但set内置命令的noclobber选项尚未启用,即使文件已经存在,重定向也会尝试打开文件。

追加方式的输出重定向

追加方式的输出重定向表示以追加写的方式打开指定的文件(文件名是单字替换后的结果)作为文件描述符n。如果未指定n,默认的文件描述符是1,即打开指定的文件作为标准输出。如果文件不存在,创建新的文件。

追加输出重定向的一般语法格式如下:

        [n]>>word

标准输出与标准错误输出的重定向

把标准输出(文件描述符1)与标准错误输出(文件描述符2)均重定向到指定的文件,文件的名字是单字替换后的结果。

标准输出与标准错误输出重定向具有两种语法格式:

        &>word

        >&word

在上述两种语法格式中,第一种为最佳选择。实际上,上述两种语法格式也可以改写成下列等价的语法格式:

word 2>&1

追加方式的标准输出与标准错误输出重定向

以追加写的方式,把标准输出(文件描述符1)与标准错误输出(文件描述符2)均重定向到指定的文件,文件的名字是单字替换后的结果。

标准输出与标准错误输出追加重定向的一般语法格式如下:

        &>>word

上述语法格式也可以改写成下列等价的语法格式:

        >>word 2>&1

复制文件描述符

下列重定向符号用于复制输入文件描述符:

        [n]<&digit

如果digit是一位或多位数字,使用该数字指定的文件描述符替代n指定的文件描述符。如果前者没有以输入方式打开,将会出现重定向错误。如果digit是“-”,则关闭文件描述符n。如果未指定n,则假定为标准输入(文件描述符0)。

下列重定向符号用于复制输出文件描述符:

        [n]>&digit

如果未指定n,假定为标准输出(文件描述符1)。如果digit指定的文件描述符没有以输出方式打开,将会出现重定向错误。作为一个特例,如果未指定n,且digit也不是一位或多位数字,按照前几节的说明重定向标准输出与标准错误输出。

移动文件描述符

利用下列重定向符号,可以把digit表示的文件描述符改为文件描述符n,然后关闭文件描述符digit。如果未指定n,默认的文件描述符为0,即标准输入。

        [n]<&digit-

类似地,利用下列重定向符号,可以把digit表示的文件描述符改为文件描述符n,然后关闭文件描述符digit。如果未指定n,默认的文件描述符为1,即标准输出。

        [n]>&digit-

以读写方式打开文件描述符

利用下列重定向符号,可以使用word作为文件名,采用读写方式,以文件描述符n打开对应的文件。如果未指定n,默认的文件描述符为0。如果文件不存在,则创建新的文件。

        [n]<>word

Here文档

Here文档也是一种重定向,只是令Shell从当前的文件中读取输入数据,直至遇到仅包含分界符(后面不存在任何空格)的数据行为止。读取的所有数据行均用作命令的标准输入。

Here文档的语法格式如下:

        <<[-]word
            here-document
        delimiter

在上述语法格式中,不允许单字word执行变量替换、命令替换、算术替换以及文件名生成。如果word中的任何字符加了引用,here-document中的数据不能执行任何替换,而且分界符delimiter应是word删除引用后的结果。如果word未加引用,here-document中的数据可以执行变量替换、命令替换以及算术替换等。在最后一种情况下,忽略字符序列“\换行符”,需要时,必须使用“\”引用特殊字符“\”、“$”与“`”。

如果重定向符号是“<<-”,删除包括分界符在内所有数据行前面的制表符,使得Shell脚本中的Here文档能够适当地缩进,达到错落有致的效果。

Here字符串

Here字符串是Here文档的一种变体,其语法格式如下:

        <<<word

其中的word可以执行适当的替换,通过标准输入提供给命令。

命令别名

命令别名允许使用一个字符串替换简单命令的第一个单字。Shell维护一组命令别名,可以使用alias与unalias内置命令设置或清除。如果未加引用,Shell将会检查每个简单命令的第一个单字,确定是否存在匹配的命令别名。如果存在,使用命令别名的定义替换该单字。字符“/”、“$”、“`”、“=”及任何Shell元字符或引用字符不能出现在命令别名的名字中。但替换字符串可以包含任何有效的Shell输入,包括Shell元字符。Shell仅对替换字符串的第一个字作为命令别名进行测试与替换,但不会对替换后的同一单字再做第二次替换,从而防止递归替换。例如,假定“ls -F”是ls命令的别名,只能使用“ls -F”替换ls,不能再对“ls -F”中的ls进行替换。如果别名定义的最后一个字符是空格,还要检查紧随命令别名之后的下一个命令是否需要执行命令别名替换。

使用alias内置命令可以创建和列出命令别名,使用unalias内置命令可以删除命令别名。

在用作替换字符串的命令别名定义中,不能使用参数。如果需要参数,应当使用Shell函数,参见“Shell函数”一节。

除非使用shopt内置命令设置了Shell选项expand_aliases,在非交互Shell中不允许执行命令别名替换。

有关命令别名的定义和使用规则有时可能会引起混淆。在执行任何一个命令行之前,bash总是至少读取一个完整的输入数据行。在读取命令而非执行命令时,执行命令别名的替换。因此,直至读取下一行输入数据时,出现在同一命令行上但作为单独命令的命令别名定义才起作用。同一命令行上命令别名定义之后的命令不会识别新的命令别名。在调用函数时,这种处理方式会存在问题。在读取函数定义而非执行函数时,才执行命令别名替换,这是因为函数定义本身就是一个组合命令。因此,直至在函数执行之后,函数中定义的命令别名才是可用的。为保险起见,应当总是把命令别名的定义放在一个单独的行上,不要在组合命令中定义命令别名。

在任何情况下,实际上均可使用Shell函数替代命令别名。

函数

Shell函数是按照Shell语法规则定义的一组命令的集合体,以便在之后调用时执行。当使用Shell函数名作为命令引用时,立即执行函数体内的一系列命令。调用的函数在当前Shell的上下文环境中执行,不会创建新的进程解释执行函数,这与Shell脚本的执行情况是不同的。

在执行函数时,函数的参数成为执行期间的位置参数。特殊参数“$#”会随时更新以反映其变化。特殊参数$0保持不变。函数执行时,Shell把FUNCNAME数组变量的第一个元素设置成函数的名字。

除了下列情况,Shell函数与调用者之间在Shell执行环境方面是等同的:函数通常不会继承调用者的DEBUG与RETURN信号捕捉设置(参见trap内置命令的说明),除非使用declare等命令定义了函数的跟踪属性,或使用“set -o”命令启用了Shell选项functrace,函数才会继承DEBUG与RETURN的信号捕捉设置。而且,除非使用“set -o”命令启用了Shell选项errtrace,函数通常也不会继承调用者的ERR信号捕捉设置。

使用local内置命令,可以声明函数的本地变量。通常,变量及变量值在函数与调用者之间是共享的。

在函数中,如果执行了return内置命令,意味着函数执行的结束,调用者从调用函数的下一个命令开始恢复执行。在恢复执行之前,还要执行与RETURN跟踪有关的任何命令。函数运行结束时,位置参数与特殊参数“$#”恢复到调用函数前的值。

使用declare或typeset内置命令的“-f”选项,可以列出函数的名字及其定义(使用“-F”选项只能列出函数的名字)。使用export内置命令的“-f”选项,可以公布函数,以便子Shell能够自动拥有函数的定义。使用unset内置命令的“-f”选项,可以删除函数的定义。注意,函数与变量不能同名,以免引起问题。

函数可以递归调用,递归调用的次数也没有限制。

算术计算

Shell支持一定的算术表达式计算功能,参见let与declare内置命令以及“算术替换”一节的说明。算术表达式的计算采用固定精度的整数,不检测是否溢出。但会跟踪0 作为除数的情形,同时提示相应的错误。运算符及其优先顺序、关联性以及数值与C语言是相同的。下面列出的运算符首先把相同优先级别的运算符并列在一起,然后按优先级的降序排列各组运算符。

        id++,id--       变量的后加1和后减1运算。
        ++id,--id       变量的先加1和先减1运算。
        -,+             一元减和加运算。
        !, ~           逻辑非与按位求反运算。
        **              指数运算。
        *,/,%           乘、除与模运算。
        +,-             加减运算。
        <<,>>       左右位移。
        <=,>=,<>    比较运算。
        ==,!=           等于和不等于运算。
        &               按位执行逻辑与运算。
        ^               按位执行逻辑异或运算。
        |               按位执行逻辑或运算。
        &&              逻辑与运算。
        ||              逻辑或运算。
        expr?expr:expr  条件运算。
        =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
                        赋值或组合赋值运算。
        expr1,expr2     逗号运算。

Shell变量可以作为操作数。在计算表达式之前,首先应执行参数替换。在表达式中,也可以直接使用名字引用变量,而不必使用参数替换语法。在按名字引用而未使用参数替换语法时,空的或未定义的Shell变量按0计算。引用时,或当使用“declare -i”内置命令把变量定义为整数变量且赋予变量一个数值时,可按表达式计算变量的值。在表达式中使用时,不需要事先把Shell变量定义为整数属性。

具有前置0的常数按八进制数值解释,前置“0x”或“0X”表示十六进制的数值。否则,数值可以按“[base#]n”形式解释,其中,base是一个表示进位的十进制整数,位于2与64之间,n是一个基于该进位的数字。如果省略了“base#”,假定是十进位,即十进制数值。大于9的数字依序采用小写字母、大写字母、“@”与“_”表示。如果base小于或等于36,可以交替使用大小写字母表示10与35之间(包括10与35本身)的数字。

算术计算是按运算符的优先顺序进行计算的,利用圆括号可以修改上述优先规则。圆括号中的子表达式优先级最高,因而首先计算。

条件表达式

条件表达式采用test、“[[ … ]]”或“[ … ]”等命令测试文件的属性,或执行字符串与算术表达式的比较。命令中内嵌的表达式可由一元或二元的操作数与算术或逻辑运算符组成。如果操作数是/dev/fd/n形式的文件名参数,检测文件描述符n。如果操作数是/dev/stdin、/dev/stdout或/dev/stderr形式的文件名参数之一,分别检测文件描述符0、1或2。

        除非特别指定,如果操作数是符号链接文件,使用符号链接文件引用的文件,而非符号链接文件本身。
        如果表达式位于“[[ … ]]”命令中,比较运算符“<”与“>”是基于当前语言环境的字符集排序的。
        -a file          如果给定的文件存在,测试结果为真
        -b file          如果给定的文件存在,且是块特殊文件,测试结果为真。
        -c file          如果给定的文件存在,且是字符特殊文件,测试结果为真。
        -d file          如果给定的文件存在,且是一个目录,测试结果为真。
        -e file          如果给定的文件存在,测试结果为真。
        -f file          如果给定的文件存在,且是一个普通文件,测试结果为真。
        -g file          如果给定的文件存在,且已设置了setgid标志位,测试结果为真。
        -h file          如果给定的文件存在,且是一个符号链接文件,测试结果为真。
        -k file          如果给定的文件存在,且已设置了黏性标志位,测试结果为真。
        -p file          如果给定的文件存在,且是一个FIFO管道文件,测试结果为真。
        -r file          如果给定的文件存在,且当前用户可读,测试结果为真。
        -s file          如果给定的文件存在,且其容量大于0,测试结果为真。
        -t fd            如果给定文件描述符fd的文件已打开,且与终端关联,测试结果为真。
        -u file          如果给定的文件存在,且已设置了setuid标志位,测试结果为真。
        -w file          如果给定的文件存在,且当前用户可写,测试结果为真。
        -x file          如果给定的文件存在,且当前用户可执行或能够检索,测试结果为真。
        -O file          如果文件存在,且归当前有效用户ID的用户拥有,测试结果为真。
        -G file          如果文件存在,且归当前有效用户组ID的用户组拥有,测试结果为真。
        -L file          如果给定的文件存在,且是一个符号链接文件,测试结果为真。
        -S file          如果给定的文件存在,且是一个套接字,测试结果为真。
        -N file          如果给定的文件存在,且自上次阅读以来文件已经修改过,测试结果为真。
        file1-nt file2   以修改时间为准,如果file1file2还新,或者file1存在,但file2不存在,测试结果
                        为真。
        file1-ot file2   以修改时间为准,如果file1file2还旧,或file2存在,但file1不存在,测试结果为真。
        file1-ef file2   如果file1file2引用同一设备,且具有相同的信息节点号,结果为真。
        -o optname       如果Shell选项optname已经启用,测试结果为真。参见set命令中介绍的一系列“-o”
                        选项。
        -z str           如果给定字符串的长度为0,测试结果为真。
        str,-n str       如果给定字符串的长度大于0,测试结果为真。
        str1==str2,str1=str2
                        如果给定的两个字符串相同,测试结果为真。为保持与POSIX标准的兼容性,test命
                        令中应使用“=”。
        str1!=str2      如果给定的两个字符串不同,测试结果为真。
        str1str2      如果给定字符串str1的编码顺序优先于字符串str2,测试结果为真。
        str1str2      如果给定字符串str1的编码顺序落后于字符串str2,测试结果为真。
        arg1 op arg2      其中op是二元算术运算符“-eq”、“-ne”、“-lt”、“-le”、“-gt”或“-ge”之一,
                        如果 arg1 分别等于、不等、小于、小于等于、大于或大于等于arg2,返回真。arg1arg2可以是正整数或负整数。

简单命令的替换步骤

执行简单命令时,Shell按照从左到右的顺序执行下列的各种替换、赋值与重定向:

1. 解释后标记作变量赋值(位于命令名之前)与I/O重定向的单字留待之后处理。

2. 替换除变量赋值和重定向之外的单字。替换之后,如果存在任何单字,第一个单字作为命令名处理,其余的单字是参数。

3. 按照“重定向”一节的说明执行I/O重定向。

4. 在开始执行变量赋值之前,首先对每个变量赋值语句的等号之后的字符串执行波浪号替换、参数替换、命令替换、算术替换以及删除引用符号。

如果命令行中不存在命令名,变量赋值加到当前的Shell环境。否则,把变量加到欲执行命令的运行环境,但不影响当前的Shell环境。如果任何赋值语句试图为只读变量赋值,输出一条错误信息,然后退出命令,返回非0的结束状态。

如果命令行中不存在命令名,执行I/O重定向,但不影响当前的Shell环境。I/O重定向错误将会引起命令终止运行,返回非0的结束状态。

如果替换后存在一个命令名,按“运行命令”一节的说明运行命令。否则,终止命令的运行。如果某个替换中含有嵌套的命令替换,当前命令的结束状态是最后执行的一个命令替换的结束状态。如果没有命令替换,当前命令的结束状态是0。

运行命令

在命令行分解成一系列单字之后,如果其结果是一个简单的命令、一组选用的选项和参数,Shell将会采取下列动作:

如果命令名不包含斜线字符,Shell将尝试定位指定的命令。如果存在一个同名的Shell函数,按照“函数”一节所述调用相应的函数。如果不存在匹配的函数,Shell在内置命令中检索是否存在同名的命令。如果发现匹配者,调用相应的内置命令。

如果名字既非Shell函数、内置命令,也不包含斜线字符,bash开始检索PATH变量定义的每一个目录,检查其中是否包含同名的可执行文件。bash使用散列表记住可执行文件的完整路径名,参见“Shell内置命令”一节。仅当散列表中不存在调用的命令时,才会全面、依次检索PATH变量定义的目录。如果检索失败,Shell将会检索是否存在定义的Shell函数command_not_found_handle。如果函数存在,使用初始的命令、初始的选项与参数作为函数的参数调用该函数,函数的结束状态成为Shell的结束状态。如果未定义上述函数,Shell将会输出一条错误信息,然后返回127。

如果命令检索成功,或命令名中包含一个或多个斜线字符,Shell将会在另外一个运行环境中执行命名的程序。参数0设置成给定命令的名字,如果存在,其余的选项与参数作为程序的选项与参数。

如果由于文件并非可执行文件,也不是目录,导致程序执行失败,则假定文件是一个包含Shell命令的Shell脚本文件,此时将会调用一个子Shell运行脚本。子Shell本身重新初始化,就像调用了一个新的Shell处理脚本,唯一的例外是子Shell会维护父进程记录的命令的位置。

如果程序是一个文件,其起始字符串是“#!”,第一行的其余部分用于指定程序的解释程序(及其选项)。Shell调用操作系统中的指定解释程序,解释执行从第二行开始的程序正文。

命令运行环境

Shell的运行环境由下列部分组成:

● 在调用Shell时继承的打开文件,以及由exec内置命令修改的I/O重定向。

● cd、pushd或popd内置命令设置的或在调用Shell时继承的当前工作目录。

● umask内置命令设置的或从父Shell继承的文件创建掩码模式。

● 由trap内置命令设置的捕捉信号。

● 变量赋值语句设置的、set内置命令设置的或从父Shell环境继承的Shell参数。

● 在执行期间定义的或从父Shell环境继承的Shell函数。

● 调用时默认的、命令行参数启用的或设置的Shell选项。

● shopt内置命令启用的Shell选项。

● alias内置命令定义的命令别名。

● 各种进程ID,包括后台作业的进程ID、$$的值和PPID变量的值。

在执行简单命令而非内置命令或Shell函数时,将会在一个单独的运行环境中调用该命令。这一运行环境由下列部分组成。除非特别说明,其中的值是从Shell中继承的。

● Shell的打开文件,加上命令的I/O重定向指定的任何修改与补充。

● 当前工作目录。

● 文件创建模式掩码。

● 公布的Shell变量与函数,以及仅对单个命令公布的变量,或传递到环境的变量。

● 根据继承自父Shell的捕捉信号设置重新设置,父进程忽略的信号也忽略之。

在单独环境中调用的命令不会影响Shell运行环境。

命令替换、圆括号中的组合命令和异步命令是在子Shell环境中调用的,除了Shell中的信号跟踪设置(把跟踪的信号重新设置到调用时从父Shell继承来的信号设置),子Shell环境实为Shell的复制品。作为管道的一部分调用的内置命令也在子Shell环境中运行。子Shell对环境的任何修改不会影响Shell运行环境。

因执行命令替换而调用的子Shell将继承父Shell“-e”选项的值。而在非POSIX模式下运行时,bash会清除子Shell中“-e”选项的值。

如果命令后面跟有“&”后台作业符号,且未启用作业控制,命令默认的标准输入是空文件/dev/null。否则,调用的命令将会继承父Shell的文件描述符,包括重定向引起的修改。

环境

当调用一个程序时,Shell将会为程序提供一个称作环境的字符串数组。其中包括一组具有下列形式的赋值语句:

      name=value

Shell提供若干运行环境的操作方法。调用时,Shell将会扫描自己的运行环境,对于发现的每一个名字,创建一个参数,自动向子进程公布。运行的命令将会继承此环境。利用export与“declare -x”内置命令,可以把参数和函数加到环境中或从环境中删除。如果环境中的参数值被修改,新的参数值将替代先前的参数值成为环境的一部分。任何运行的命令继承的环境由Shell的初始环境,以及在Shell运行期间的修改部分组成,因此最终继承的环境需要减去内置命令删除的参数与函数,加上利用export与“declare -x”增加的参数与函数。

在任何简单命令或函数之前插入参数赋值语句,可以通过参数化的方法,把环境临时传递给简单命令或函数,参见“参数(变量)”一节的说明。这些赋值语句仅影响同一命令行上的简单命令或函数的环境。

如果设置了set内置命令的“-k”选项,不仅命令前的参数赋值会放置在命令的环境中,其他所有的参数赋值也会放置在命令的环境中。

当bash调用一个外部命令时,特殊变量“$_”被设置成命令的完整路径文件名,然后传递到命令的环境中。

结束状态

命令终止执行后返回的结束状态是由waitpid()系统调用或等价的函数返回的值。结束状态位于0~255之间。Shell内置命令与组合命令的结束状态也限定于这个范围。在一定情况下,Shell将会使用特殊的值表示特定的错误情形。

对于Shell而言,命令终止运行后返回结束状态0表示命令已成功地运行,返回非0的结束状态表示运行失败。当命令由于信号n而终止运行时,bash使用128+n作为其结束状态。

如果命令不存在,运行该命令的子进程将返回结束状态127。如果命令存在,但无法执行,返回的结束状态是126。

如果一个命令由于替换或重定向期间出现错误导致运行失败,其结束状态是一个大于0的数字。

如果运行成功,Shell内置命令返回0(真),运行时如果出现错误返回非0(假)。如果用法有误,所有的内置命令均返回2。

除非本身出现用法或语法错误(返回非0的结束状态),bash将会返回其运行的最后一个命令的结束状态。参见exit内置命令的说明。

信号

当处于交互方式时,如果未提供任何trap语句,bash将会忽略SIGTERM信号(故“kill 0”不会终止交互Shell),但可以捕捉和处理SIGINT信号。在任何情况下,bash通常会忽略SIGQUIT信号。如果启用了作业控制功能,bash还会忽略SIGTTIN、SIGTTOU和SIGTSTP信号。

bash运行的外部命令通常都具有信号处理模块,能够处理从父进程继承的信号设置。当作业控制尚未启用时,除了继承的信号处理模块,异步命令还会忽略SIGINT与SIGQUIT信号。作为命令替换的结果,命令运行时也会忽略键盘生成的作业控制信号SIGTTIN、SIGTTOU与SIGTSTP。

在收到信号SIGHUP时,Shell通常会终止运行。在退出之前,交互Shell将会向所有的作业(包括运行和停止运行的作业)重新发送SIGHUP信号。对于停止运行的作业,尚需发送SIGCONT信号,确保其能够收到SIGHUP信号。为防止Shell向特定的作业发送信号,应使用disown内置命令,从作业表中删除相应的作业,或使用“disown -h”命令禁止相应的作业收到SIGHUP信号。

如果已经使用内置命令设置了Shell选项huponexit,当交互的注册Shell终止运行时,bash会向所有的作业发送SIGHUP信号。

如果正在等待一个命令的完成时收到需要捕捉的信号,在命令完成之前bash不会执行trap命令定义的处理动作。当bash正在等待一个通过wait内置命令提交的异步命令期间收到需要捕捉的信号时,将会引起wait内置命令立即转而执行trap命令定义的处理动作,最后返回一个大于128的结束状态。

作业控制

作业控制提供一种机制,使用户能够有选择性地暂停(挂起)进程的执行,之后再从某个时间点开始继续(恢复)运行。

Shell维护一个当前执行的作业表,利用内置命令jobs可以列出系统当前维护的作业。当bash启动一个异步运行的后台作业时,将会显示类似下列的信息:

[1] 2568

其中,方括号中的1是作业号,后面的数字2568是后台作业的进程ID。一个作业可由多个进程组成,bash以作业为单位实现作业控制。

为了便于实现作业控制的用户界面,操作系统采用当前终端进程组ID的概念。进程组中的成员(其进程组ID等于当前终端进程组ID)接受键盘生成的信号,如SIGINT,进程处于前台运行方式。后台进程是其进程组ID不同于终端进程组ID的进程,这样的进程不受键盘生成信号的影响。如果用户运行了“stty tostop”命令,只有前台进程才能读写终端,尝试读写终端的后台进程将会收到内核终端驱动程序发送的SIGTTIN或SIGTTOU信号,除非事先已做了捕捉处理,通常会挂起后台进程。

如果操作系统支持或bash启用了作业控制,当进程正在运行时,按下Ctrl-Z组合键将会停止进程的运行,把控制权交回bash。在进程尝试读取终端输入时,按下Ctrl-Y组合键将会停止进程的运行,把控制权交回bash。之后用户可以操控暂停运行的进程:使用bg命令令进程以后台方式运行,使用fg命令令进程以前台方式运行,或使用kill命令终止进程的运行。

在bash中,可以使用多种方法指定作业。百分号字符“%”用于指定作业号,作业号n写作%n,表示第n个作业。也可以使用启动作业的命令名或命令行的部分字符串指定作业。其中,“%str”表示起始字符串为str的命令行(如命令名)指定的作业,“%?str”表示包含str的命令行指定的作业。例如,“%find”表示暂停运行的find作业。如果前缀匹配多个作业,bash将会显示一条错误信息。而“%?ce”表示命令行包含字符串ce的任何作业。同样,如果字符串匹配多个作业,bash将会输出一条错误信息。“%%”与“%+”均引用当前作业,即最近一个以前台方式运行而暂停的作业或以后台方式启动的作业。使用“%-”可以引用前一个作业。如果当前只有一个作业,“%+”与“%-”引用的是同一个作业。在jobs命令的输出信息中,当前作业总是存在一个“+”标记,前一个作业存在一个“-”标记。单独一个“%”也表示当前作业。

直接引用一个作业号相当于把相应的作业从后台置于前台运行方式。也就是说,“%1”等同于输入“fg %1”命令。类似地,“%1 &”意味着把第一个作业置于后台运行方式,等价于运行“bg %1”命令。

无论何时,Shell会立即获悉作业的状态变化,但bash通常会等待直至将要输出命令提示符的前一刻,才会报告作业的状态变化,以免干扰其他任何输出。如果已经启用了set内置命令的“-b”选项,bash会在获悉作业状态变化时立即报告。

当作业处于暂停运行状态,或已经使用内置命令启用了Shell选项checkjobs时,如果尝试退出bash(运行exit命令或按下Ctrl-D组合键),bash将会输出一条警告信息。如果已经启用了checkjobs选项,bash还会列出当前存在的作业及其运行状态(也可以使用jobs内置命令查询作业的状态)。如果再次尝试退出bash(两次退出Shell之间未输入其他任何命令),bash不会再输出警告信息,而是立即终止暂停运行的任何作业,退出bash。

命令提示符

在交互访问系统的过程中,当准备接受命令时,bash将会显示PS1变量的值,作为主提示符。当需要进一步读取数据才能输入完整的命令时,显示PS2变量的值作为次级命令提示符。bash允许用户使用下列转义字符设置PS1或PS2变量,从而定制命令提示符。

        \a       警示音字符(ASCII编码07)。
        \d       以“Weekday Month Date”的格式显示日期,如“Tue May 26”。
        \D{fmt}   把格式字符串fmt传递给strftime(3)函数,再把返回结果插入提示字符串中。如果格式字符
                串是空的,意味着采用本地语言环境特定的时间表示。注意,花括号必须存在。
        \e       ESC字符(ASCII编码033)。
        \h       显示系统的主机名(不包括域名)。
        \H      显示系统的规范主机名(包括域名)。
        \j       显示Shell当前管理的后台作业的数量(包括当前正在运行或暂停的作业)。
        \l       显示简化的当前终端设备名(省略“/dev/”部分)
        \n       换行符。
        \r       回车符。
        \s       显示当前所用Shell的名字。
        \t       以“HH:MM:SS”格式的24小时制显示当前时间,如“15:30:00”。
        \T       以“HH:MM:SS”格式的12小时制显示当前时间。
        \@      以“AM/PM”格式的12小时制显示时间,如“03:30 PM”或“10:12 上午”。
        \A      以“HH:MM”格式的24小时制显示当前时间。
        \u       显示当前的用户名。
        \v       显示bash的版本信息,如2.00。
        \V      显示bash的版本与修订信息,如2.00.0。
        \w      显示当前工作目录的完整路径名($HOME缩写成一个波浪号)。
        \W      显示当前工作目录的最后一个子目录名($HOME缩写成一个波浪号)。
        \!       显示当前命令在命令历史记录中的命令编号。
        \#       显示当前命令自调用bash迄今的序号(从1开始编号)。
        \$       输出表示用户身份的提示符。超级用户为“#”,普通用户为“$”。
        \nnn     八进制数值编码nnn表示的字符。
        \\       在命令提示符中插入一个反斜杠。
        \[       标志一个不可打印字符序列的开始,以便在命令提示符中嵌入一个终端控制序列。
        \]       表示不可打印字符序列的结束。

上述所谓的命令编号与命令历史中的命令编号通常是不同的:命令历史中的命令编号是命令在命令历史缓冲区中的位置,其中的命令可能包括从命令历史文件中恢复的命令。而命令编号是命令在当前Shell会话期间执行的命令序列中的位置。

Readline

readline是一个库函数,用于处理在交互Shell中读取的键盘输入。在建立了键序列与readline函数(或称readline命令)的捆绑关系之后,通过按键,可以调用相应的readline命令,执行命令行编辑。调用Shell时,如果指定了“--noediting”选项,可以禁用readline行编辑功能。此外,read内置命令的“-e”选项也支持行编辑。通常,行编辑命令类似于emacs编辑器中的命令(bash也支持vi风格的行编辑)。无论何时,使用set内置命令的“-o emacs”或“-o vi”选项可以启用选定的行编辑功能。在Shell运行期间,使用set内置命令的“+o emacs”或“+o vi”选项也可以关闭行编辑功能。

本节采用emacs风格的记号表示按键。其中,C-x表示Ctrl-x,简记为^X。M-x表示Meta-X。在不支持Meta键的键盘上,可以使用ESC x(先按ESC键,释放后再按x键)或Alt-x(同时按下Alt与x键)替代M-x。M-C-x组合键意味着先按ESC键,释放后再同时按下Ctrl与x键。

Readline初始化

通过创建或修改inputrc初始化文件,可以定制readline库函数。其中,/etc/inputrc是系统初始化文件,~/.inputrc(INPUTRC变量的默认值)是用户初始化文件。在初始化文件中,可以定义readline命令与键序列的捆绑关系,也可以定义readline变量。

在启动过程中,Shell将会读取inputrc初始化文件,定义键序列与readline函数的捆绑关系,设置readline变量。

在定义键序列与readline函数的捆绑关系时,可以采用下列语法格式:

        keyname:function-name

其中,keyname 是键序列的英文符号名,如常规的普通字符键,DEL(RUBOUT)、ESC、NEWLINE(LFD)、RETURN(RET)、SPACE(SPC)和TAB等特殊字符键,以及含有Control或Meta前缀的组合键。function-name是readline函数或命令的名字。

在下面的例子中,Ctrl-U组合键捆绑到universal-argument命令,M-Rubout(M-DEL)捆绑到backward-kill-word命令。

        Control-u: universal-argument
        Meta-Rubout: backward-kill-word

此外,也可以采用下列语法格式定义键序列与readline函数的捆绑关系:

        "keyseq":function-name

其中,keyseq是转义的键序列,包括GNU Emacs风格的转义序列,以及普通的Shell转义字符序列。

在下面的例子中,“C-u”表示把Ctrl-U组合键捆绑到universal-argument命令,“C-x C-r”表示把Ctrl-X与Ctrl-R捆绑到re-read-init-file命令。

        "\C-u": universal-argument
        "\C-x\C-r": re-read-init-file

下面是一组完整的GNU Emacs风格的转义序列:

        \C-      Ctrl键前缀。
        \M-      Meta键前缀。
        \e       ESC字符。
        \\       反斜线字符。
        \"       双引号文字本身。
        \'       单引号文字本身。

除了上述转义序列,bash还支持普通的Shell转义序列:

        \a       警示音。
        \b       退格符。
        \d       删除键。
        \f       换页符。
        \n       换行符。
        \r       回车符。
        \t       制表符。
        \v       纵向制表符。
        \nnn     由1位至3位八进制数值nnn表示的8位编码的字符。
        \xHH     由1位或两位十六进制数值HH表示的8位编码的字符。

注意,使用bash的bind内置命令,可以显示或修改当前键序列与readline函数的捆绑关系。

Readline变量

readline提供若干变量,用于定制其行为。在inputrc文件中,可以采用下列语句形式设置readline变量:

      set variable-name value

除了普通赋值形式,readline变量可以赋予On或Off值(大小写字母均可)。在读取变量时,空串、NULL、on或1等价于On,off或0等其他情况等价于Off。readline支持的部分变量及其默认值简述如下:

        comment-begin(‘‘#’’)
            当执行readline的insert-comment命令时,可以插入定义的字符串。这个命令捆绑到“M-#”(emacs
            模式)或“#”(vi命令模式)键。
        completion-ignore-case (Off)
            如果设置为On,readline在执行文件名匹配与补缺时不区分大小写字母。
        disable-completion (Off)
            如果设置为On,readline禁止单字补缺。
        editing-mode (emacs)
            控制采用哪一种行编辑模式。当前支持的行编辑模式是emacs(默认)与vi。
        echo-control-characters (On)
            如果设置为On,readline将会回显键盘生成信号的相应字符。
        enable-keypad (Off)
            设置为On时,readline将试图启用应用小键盘。某些系统需要使用这个变量启用箭头键。
        expand-tilde (Off)
            如果设置为On,当readline尝试进行单字补缺时执行波浪号替换。
        history-size (0)
            设置命令历史缓冲区能够保存的命令历史记录的最大数量。如果设置为 0,命令历史缓冲区能够
            保存的命令历史记录没有限制。
        horizontal-scroll-mode (Off)
            如果设置为On,当命令行大于屏幕宽度时,readline将会采用单行显示方式水平滚动显示,而不
            是折行显示。
        isearch-terminators (‘‘C-[C-J’’)
            用于设置能够终止增量检索的字符串。如果这个变量没有赋值,利用ESC与C-J可以终止增量检索。
        mark-directories (On)
            如果设置为On,补缺后的目录名后面将会附加一个斜线字符。
        mark-modified-lines (Off)
            如果设置为On,在显示命令历史记录时,修改过的命令行前面将会插入一个星号标记。
        mark-symlinked-directories (Off)
            如果设置为On,当补缺的名字是一个指向目录的符号链接文件时,将会在后面附加一个斜线字符。
        match-hidden-files (On)
            如果设置为On,在执行文件名补缺时,readline也会匹配文件名首字符为句点“.”的隐藏文件,
            除非用户提供的文件名包含前置句点。
        page-completions (On)
            如果设置为On,当可能的补缺超过一个屏幕的容量时,readline将会使用类似于more命令的分页
            显示方式显示可能的补缺。
        print-completions-horizontally (Off)
            如果设置为On,readline将会按照字符顺序先横向,再纵向,逐行显示可能的补缺。
        show-all-if-ambiguous (Off)
            如果设置为On,具有多个可能补缺的单字将导致Shell立即列出匹配者,而不是发出警示音。
        visible-stats (Off)
            如果设置为On,在列出可能的补缺时,一个表示文件类型(由stat(2)系统调用提供)的字符将会
            附加在文件名的后面。

命令行检索

Readline提供若干检索命令,用于检索命令历史缓冲区中包含指定字符串的命令行。检索分为增量检索与非增量检索两种检索方式。

按下Ctrl-S与Ctrl-R组合键,可以分别进入正向与反向增量检索。

增量检索从用户输入字符开始,每输入一个字符,readline将会显示最近一个匹配迄今输入的所有字符串的命令行。采用增量检索方式,可以逐步输入适当数量的字符,直至发现期望的命令行。

isearch-terminators变量定义的值用于终止增量检索。如果变量未赋值,可以使用ESC与Ctrl-J组合键终止增量检索,接受并执行当前命令行。直接按下Enter键,也可以终止增量检索,接受并执行当前命令行。

使用Ctrl-G组合键,可以撤销增量检索,恢复检索前的命令行原状。

当终止增量检索时,包含检索字符串的命令行将会成为当前命令行。此时可以接受并执行当前命令行,也可以编辑命令行。

非增量检索意味着在开始检索之前需要读取整个检索字符串。检索字符串可以来自用户的输入,也可以是当前行的部分内容。

Readline命令

下面是一组readline命令,命令名后面的圆括号内是默认绑定的键序列。没有给出键序列表示尚未绑定。

在输入readline命令之前,可以提供一个数值参数,用作命令动作的重复计数。数值参数(如负数)有时也用作一个标记,表示命令动作的方向。

当用readline命令删除数据时,这些数据通常会保存在一个环形缓冲区中,以便之后能够回收再用。连续的删除命令将会导致删除的数据合并为一个数据单位,因而能够一次取回。如果中间输入了不删除数据的命令,将会分割环形缓冲区中的数据处理单位。

光标移动命令

        beginning-of-line(^A)     把光标移至当前行的行首。
        end-of-line(^E)           把光标移至当前行的行尾。
        forward-char(^F)          光标前移一个字符位置。
        backward-char(^B)         光标后移一个字符位置。
        forward-word(M-f)         把光标前移至当前或下一个字(由字母和数字组成)的字尾。
        backward-word(M-b)     把光标后移至当前或前一个字(由字母和数字组成)的字首。
        shell-forward-word        光标前移至下一个字(由非引用的Shell元字符分隔的字符串)的字尾。
        shell-backward-word       光标后移至当前或前一个字(由非引用的Shell元字符分隔的字符串)的字
                                  首。
        clear-screen(^L)          清除屏幕,把当前的命令行移至屏幕的第一行。
        redraw-current-line       刷新当前行。

命令历史操作命令

        accept-line (Newline, Return)
                                    接受当前行。如果当前行非空,把当前行加到命令历史缓冲区中(需满足
                                    HISTCONTROL变量的要求)。
        previous-history(^P)        取回命令历史缓冲区中的前一个命令行,命令行指针相应地上移。
        next-history(^N)            取回命令历史缓冲区中的下一个命令行,命令行指针相应地下移。
        beginning-of-history (M-<)
        end-of-history(M->)        把命令行指针移至命令历史缓冲区的最后一行,即当前的输入行。
                                    把命令行指针移至命令历史缓冲区的第一行。
        reverse-search-history(^R)  从当前命令行开始反向检索。命令行指针相应地上移。这是一个增量检索。
        forward-search-history(^S) 从当前命令行开始正向检索。命令行指针相应地下移。这是一个增量检索。
        non-incremental-reverse-search-history (M-p)
                                    使用用户提供的字符串,采用非增量检索的方式,从当前命令行开始反向检
                                    索命令历史缓冲区。
        non-incremental-forward-search-history (M-n)
                                    使用用户提供的字符串,采用非增量检索的方式,正向检索命令历史缓冲区。
        history-search-forward      使用当前行起始位置至光标位置间的字符串,正向检索命令历史缓冲区。这
                                    是一个非增量检索。
        history-search-backward     使用当前行起始位置至光标位置间的字符串,反向检索命令历史缓冲区。
                                    这是一个非增量检索。
        yank-nth-arg(M-C-y)         在光标位置插入前一个命令的第一个参数(通常是第二个单字)。如果提供
                                    了数值参数n,插入前一个命令的第n个单字(从0开始计数)。如果数值
                                    参数n是负数,插入前一个命令从行尾开始计数的第n个单字。
        yank-last-arg(M-.,M-_)      在光标位置插入前一个命令的最后一个参数(即最后一个单字)。如果提
                                    供了数值参数n,其结果等同于yank-nth-arg命令。连续地调用yank-last-arg
                                    命令,将会反向遍历命令历史缓冲区,依次选取不同命令行的最后一个参
                                    数。
        shell-expand-line(M-C-e)    如同Shell做的一样,执行命令别名与命令历史替换,以及其他Shell替换。
        history-expand-line(M-^)    在当前行上执行命令历史替换。
        magic-space                 在当前行上执行命令历史替换,并插入一个空格。
        alias-expand-line           在当前行上执行命令别名替换。
        history-and-alias-expand-line在当前行上执行命令历史与命令别名替换。
        insert-last-argument (M-., M-_)
                                    同yank-last-arg命令。
        operate-and-get-next(^O)    接受当前行作为命令予以执行,并从命令历史缓冲区中摘取相对于当前行
                                    的下一个命令行进行编辑,忽略任何参数。
        edit-and-execute-command (C-xC-e)
                                    针对当前命令行调用编辑器,把编辑后的结果作为Shell命令予以执行。bash
                                    将会依次尝试调用VISUAL和EDITOR变量定义的编辑器,以及emacs编
                                    辑器。

文本修改命令

        delete-char(^D)          删除光标位置的字符。
        backward-delete-char (Delete)
                                    删除光标位置(左边)的字符。当给定一个数字参数时,把删除的文本保存
                                    在环形缓冲区中。
        quoted-insert(^Q,^V)        把随后输入的特殊字符加到当前行中。例如,如果需要插入^M字符,可在
                                    按下^V键之后,再按^M键。
        tab-insert(^V TAB)           插入一个制表符。
        self-insert(a,b,A,1,!,...)  插入输入的字符。
        transpose-chars(^T)         交换光标前与光标位置的两个字符,把光标移至下一个字符位置。如果光标
                                    位于行尾,交换光标之前两个字符的位置。
        transpose-words(M-t)        抓取光标之前的单字,移至光标之后,同时把光标移至字移动后的新位置。
                                    如果光标位于行尾,意味着交换当前行的最后两个字。
        upcase-word(M-u)            把当前或紧随其后的单字均改成大写字母。如果给定了一个负数参数,把先
                                    前的字均改成大写字母,但不移动光标。
        downcase-word(M-l)          把当前或紧随其后的单字均改成小写字母。如果给定了一个负数参数,把先
                                    前的字均改成小写字母,但不移动光标。
        capitalize-word(M-c)        把当前或紧随其后的单字均改成大写字母。当给定一个负数参数时,把先前
                                    的字均改成大写字母,但不移动光标。
        overwrite-mode              开关覆盖模式。如果明显提供了正数参数,切换到覆盖模式。如果明显提供
                                    了负数参数,切换到插入模式。这个命令仅适用于emacs行编辑,初始的工
                                    作模式是插入模式。

删除与复制命令

        kill-line(^K)             删除从当前光标位置至行尾的任何字符。
        backward-kill-line (^X Rubout)
                                  删除从当前光标位置至行首的任何字符。
        unix-line-discard(^U)     删除从当前光标位置至行首的任何字符。删除的字符串保存在环形缓冲区中。
        kill-whole-line           删除当前文本行的所有字符,不管光标位于当前行的什么位置。
        kill-word(M-d)            删除从当前光标位置至字尾的任何字符。如果光标位于两个字之间,删除从
                                  当前光标位置至下一个字的字尾的字符。单字由字母和数字组成。
        backward-kill-word (M-Rubout)
                                  删除光标位置之前的单字(由字母和数字组成),包括光标所在单字的前半
                                  部分。
        shell-kill-word(M-d)      删除从光标位置至当前字尾的任何字符。如果光标位于两个字之间,删除从
                                  当前光标位置至下一个字的字尾的字符。单字是以非引用的Shell元字符作
                                  为分隔符的。
        shell-backward-kill-word (M-Rubout)
                                  删除光标位置之前的单字(以非引用的Shell元字符作为分隔符),包括光
                                  标所在单字的前半部分。
        unix-word-rubout(^W)      删除光标位置之前的单字(使用空白字符作为分隔符),包括光标所在单字
                                  的前半部分。删除的字符串保存在环形缓冲区中。
        unix-filename-rubout      删除光标位置之前的单字(使用空白字符或斜线字符作为分隔符)。删除的
                                  文本保存在删除环形缓冲区中。
        delete-horizontal-space (M-\)
                                  删除当前光标位置前后的所有空格与制表符。
        kill-region               删除当前区域(光标位置与标记间的缓冲区)中的文本。
        copy-region-as-kill       把区域中的文本复制到环形缓冲区中。
        copy-backward-word        把光标位置之前的单字(由字母和数字组成)复制到环形缓冲区中。
        copy-forward-word         把光标位置之后的单字(由字母和数字组成)复制到环形缓冲区中。
        yank(^Y)                  复制环形缓冲区顶部的数据,置于当前行的光标位置。

数字参数命令

        digit-argument (M-0, M-1, ..., M--)
                                   用于输入数值参数 0~9。每次输入一位数字,连续输入可以组成一个多位
                                   数的数值。M--表示引入一个负数。
        universal-argument         另外一种数值参数输入方法。如果命令后面跟有一位或多位数字(或选用的
                                   前置负号),这些数字即可组成一个数值参数。如果命令后面既非数字也非
                                   负号,表示后续命令的数值参数是4,连续输入这个命令两次,后续命令的
                                   数值参数是16(4×4),以此类推。
补缺命令
        complete(TAB)              针对光标之前的字符串,尝试执行补缺。bash依次尝试按变量(如果字符
                                   串的首字符为“$”)、用户名(如果字符串的首字符为“~”)、主机名
                                  (如果字符串的首字符为“@”)或命令(包括命令别名和函数)进行补缺。
                                   如果匹配失败,尝试执行文件名补缺。
        possible-completions(M-?) 针对光标之前的字符串,列出可能的补缺。
        insert-completions(M-*)    针对光标前的字符串,使用readline的possible-completions命令生成的所有
                                   补缺替换该字符串。
        complete-filename(M-/)     针对光标之前的字符串,尝试执行文件名补缺。
        possible-filename-completions (C-x /)
                                   针对光标之前的字符串,列出可能的文件名补缺。
        complete-username(M-~)    针对光标之前的字符串,尝试执行用户名补缺。
        possible-username-completions(C-x ~)
                                   针对光标之前的字符串,列出可能的用户名补缺。
        complete-variable(M-$)     针对光标之前的字符串,尝试执行Shell变量补缺。
        possible-variable-completions (C-x $)
                                   针对光标之前的字符串,列出可能的Shell变量补缺。
        complete-hostname(M-@)     针对光标之前的字符串,尝试执行主机名补缺。
        possible-hostname-completions (C-x @)
                                   针对光标之前的字符串,列出可能的主机名补缺。
        complete-command(M-!)      针对光标之前的字符串,尝试执行命令名补缺。命令补缺使用字符串依次
                                   匹配命令别名、保留字、Shell函数、内置命令以及可执行的命令文件。
        possible-command-completions (C-x !)
                                   针对光标之前的字符串,列出可能的命令名补缺。
        dynamic-complete-history (M-TAB)
                                   针对光标之前的字符串,使用命令历史缓冲区中的命令行尝试进行补缺。
        complete-into-braces(M-{)  执行文件名补缺,把一组可能的补缺插入一对花括号中,以便补缺的一组
                                   文件名可用于Shell的花括号扩展。

其他命令

        re-read-init-file(C-x C-r)   读入inputrc文件的内容,合并其中的readline命令与键序列的捆绑定义与
                                    变量赋值。
        abort(^G)                   终止当前的编辑命令,同时向终端发出警示音。
        prefix-meta(ESC)            使用ESC替代Meta键,使得随后输入的字符x等价于Meta-x键。
        undo(C-_,C-x C-u)            逐步取消先前的编辑动作。对于每一行,readline会分别记住每个单独的编
                                    辑动作。
        revert-line(M-r)            撤销对当前行的任何修改,这相当于多次执行撤销命令,把当前行恢复原状。
        tilde-expand(M-&)           对当前的单字执行波浪号替换。
        set-mark(C-@,M-<space>) 在当前的光标位置设置标记。如果提供了数值参数,按数值指定的位置设
                                    置标记。
        exchange-point-and-mark(C-x C-x)
                                    交换当前的光标位置与标记。
        character-search(^])        读取一个字符,把光标移至该字符的下一个出现位置。负数参数意味着检索
                                    前一个出现位置。
        character-search-backward (M-C-])
                                    读取一个字符,把光标移至该字符的前一个出现位置。负数参数意味着检索
                                    下一个出现位置。
        insert-comment(M-#)         如果未提供数值参数,把readline的comment-begin变量值插入当前行的行
                                    首。如果提供了数值参数,这个命令相当于一个开关:如果行首字符不匹配
                                    comment-begin变量的值,插入该变量值。否则,删除行首的comment-begin
                                    字符。comment-begin变量的默认值能够把当前行设置成Shell注释行。如
                                    果数值参数导致注释字符的删除,将会把当前行交由Shell执行。
        glob-complete-word(M-g)     按照文件名生成模式处理光标位置之前的单字,单字后面隐含着一个星
                                    号。这个文件名模式用于生成一组匹配的文件名,作为可能的文件名补
                                    缺。
        glob-expand-word(C-x*)      按照文件名生成模式处理光标位置之前的单字,插入一组匹配的文件名,
                                    以替代该单字。如果提供了数值参数,在执行文件名生成之前,在单字后
                                    面附加一个星号。
        glob-list-expansions(C-x g) 显示由glob-expand-word命令生成的一组文件名,刷新当前行。如果提供
                                    了数值参数,执行文件名生成之前在单字后面附加一个星号。
        dump-functions              列出readline的所有命令及其捆绑的键序列。如果提供了数值参数,按照
                                    inputrc文件要求的格式输出。
        dump-variables              列出readline的所有变量及其设置。如果提供了数值参数,按照inputrc文
                                    件要求的格式输出。
        display-shell-version (C-x C-v)
                                    显示当前bash实例的版本信息。