shell命令行处理过程
1. 从一个文件(*参见 Shell脚本::), 或作为调用选项'-c'变元的一个字符串,
或用户终端中读取输入.
2. 依据引用规则(*参见 引用::), 将输入分割成单词和操作符. 注意这些token
被元字符分隔. 别名扩展也在这步中进行.
3. 将这些token解析为简单或复合命令(*参见 Shell命令::).
4. 进行各种shell扩展(*参见 Shell扩展::), 使扩展后的token变成命令, 变元和文件名列表.
5. 进行各种必要的重定向(*参见 重定向::), 然后从变元列表中移去重定向操作
符和他们的操作数.
6. 执行该命令(*参见 命令的执行::).
7. 可选地等待该命令执行结束并收集其退出状态(*参见 退出状态::).
参考资料:
Bash Man pages
DESCRIPTION
Bash 是一中兼容shell命令语言的翻译器,它从标准输入终端或者文件中读入命令并翻译执行。Bash 拥有与 ksh 和 csh 不同的有用特性。
Bash 意在实现一个符合IEEE POSIX 标准(IEEE Standard 1003.1)的 shell 和 实用工具接口,能被缺省配置成与POSIX兼容。
OPTIONS
除了在内建命令set的描述中指出的单字符的 shell 选项之外,bash还能在启动时选用以下的命令选项:In addition to the single-character shell options documented in the description of the set builtin command, bash interprets the following options when it is invoked:
-c string If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.
-i If the -i option is present, the shell is interactive.
-l Make bash act as if it had been invoked as a login shell (see INVOCATION below).
-r If the -r option is present, the shell becomes restricted (see RESTRICTED SHELL below).
-s If the -s option is present, or if no arguments remain after option processing, then commands are read from the standard input. This option allows the positional parameters to be set when invoking an interactive shell.
-D A list of all double-quoted strings preceded by $ is printed on the standard output. These are the strings that are subject to language translation when the current locale is not C or POSIX. This implies the -n option; no commands will be executed.
[-+]O [shopt_option]
shopt_option is one of the shell options accepted by the shopt builtin (see SHELL BUILTIN COMMANDS below). If shopt_option is present, -O sets the value of that option; +O unsets it. If shopt_option is not supplied, the names and values of the shell options accepted by shopt are printed on the standard output. If the invocation option is +O, the output is displayed in a format that may be reused as input.
-- A -- signals the end of options and disables further option processing. Any arguments after the -- are treated as filenames and arguments. An argument of - is equivalent to --.
Bash 也能处理一些多字符的选项,但它们必须出现在命令行中的单字符选项被识别之前的位置上。Bash also interprets a number of multi-character options. These options must appear on the command line before the single-character options to be recognized.
--debugger
Arrange for the debugger profile to be executed before the shell starts. Turns on extended debugging mode (see the description of the extdebug option to the shopt builtin below) and shell function tracing (see the description of the -o functrace option to the set builtin below).
--dump-po-strings
Equivalent to -D, but the output is in the GNU gettext po (portable object) file format.
--dump-strings
Equivalent to -D.
--help Display a usage message on standard output and exit successfully.
--init-file file
--rcfile file
Execute commands from file instead of the system wide initialization file /etc/bash.bashrc and the standard personal initialization file ~/.bashrc if the shell is interactive (see INVOCATION below).
--login
Equivalent to -l.
--noediting
Do not use the GNU readline library to read command lines when the shell is interactive.
--noprofile
Do not read either the system-wide startup file /etc/profile or any of the personal initialization files ~/.bash_profile, ~/.bash_login, or ~/.profile. By default, bash reads these files when it is invoked as a login shell (see INVOCATION below).
--norc Do not read and execute the system wide initialization file /etc/bash.bashrc and the personal initialization file ~/.bashrc if the shell is interactive. This option is on by default if the shell is invoked as sh.
--posix
Change the behavior of bash where the default operation differs from the POSIX standard to match the standard (posix mode).
--restricted
The shell becomes restricted (see RESTRICTED SHELL below).
--verbose
Equivalent to -v.
--version
Show version information for this instance of bash on the standard output and exit successfully.
INVOCATION (调用)
A login shell is one whose first character of argument zero is a -, or one started with the --login option.
An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.
The following paragraphs describe how bash executes its startup files. If any of the files exist but cannot be read, bash reports an error. Tildes are expanded in file names as described below under Tilde Expansion in the EXPANSION section.
When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.
When a login shell exits, bash reads and executes commands from the file ~/.bash_logout, if it exists.
When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist. This may be inhibited by using the --norc option. The --rcfile file option will force bash to read and execute commands from file instead of /etc/bash.bashrc and ~/.bashrc.
When bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following command were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search for the file name.
If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well. When invoked as an interactive login shell, or a non-interactive shell with the --login option, it first attempts to read and execute commands from /etc/profile and ~/.profile, in that order. The --noprofile option may be used to inhibit this behavior. When invoked as an interactive shell with the name sh, bash looks for the variable ENV, expands its value if it is defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked as sh does not attempt to read and execute commands from any other startup files, the --rcfile option has no effect. A non-interactive shell invoked with the name sh does not attempt to read any other startup files. When invoked as sh, bash enters posix mode after the startup files are read.
When bash is started in posix mode, as with the --posix command line option, it follows the POSIX standard for startup files. In this mode, interactive shells expand the ENV variable and commands are read and executed from the file whose name is the expanded value. No other startup files are read.
Bash attempts to determine when it is being run by the remote shell daemon, usually rshd. If bash determines it is being run by rshd, it reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist and are readable. It will not do this if invoked as sh. The --norc option may be used to inhibit this behavior, and the --rcfile option may be used to force another file to be read, but rshd does not generally invoke the shell with those options or allow them to be specified.
If the shell is started with the effective user (group) id not equal to the real user (group) id, and the -p option is not supplied, no startup files are read, shell functions are not inherited from the environment, the SHELLOPTS variable, if it appears in the environment, is ignored, and the effective user id is set to the real user id. If the -p option is supplied at invocation, the startup behavior is the same, but the effective user id is not reset.
DEFINITIONS(定义)
blank - space or tab (空格或制表符)
word - token (标记)
name - identifier(标识符) - 仅由 alphanumeric 和 下划线组成,并且不以 numeric 字符开始的一个字符串。
metacharacter - 用于在不被引号包围(即在引用串之外)时分割 token 的元字符。为以下之一: | & ; ( ) < > space tab
control operator - 操作控制符。为以下之一: & | ; && || ;; ( )
需要注意,大括号、中括号都不在 metacharacter 类型中,因此在随后的例子中,这两种类型的字符都需要同相邻的变量或者 reserved word 之间存在 blank 字符。# example - 1
if [ -f filename.sh -a -x filename.sh ]; then
. filename.sh
fi
# example - 2
function mfunc
{
echo "$LINENO"
}
RESERVED WORDS (保留词)
保留词是对 shell 有特殊意义的字词。Reserved words are words that have a special meaning to the shell. The following words are recognized as reserved when unquoted and either
the first word of a simple command (see SHELL GRAMMAR below) or the
third word of a case or for command:当没有被引号包围(即不在引用串内)时,并且命令栏的第一个 word 是个简单命令或者第三个 word 是 case 命令或者 for 命令时,下面的 words 被视为保留词(关键字):
! case do done elif else esac fi for function if in select then until while { } time [[ ]]
SHELL GRAMMAR (shell语法)
Simple Commands (简单命令)
A simple command is a sequence of optional variable assignments followed by blank-separated words and redirections, and terminated by a control operator. The first word specifies the command to be executed, and is passed as argument zero. The remaining words are passed as arguments to the invoked command. The return value of a simple command is its exit status, or 128+n if the command is terminated by signal n.
Pipelines
管道命令流是一个或多个命令组成的序列(sequence),命令之间通过 | 控制操作符分隔开。
常见的管道形式如下:[time -p] [!] command
[time -p] [!] command | command2 # cmd 的输出被做为 cmd2 的输入
[time -p] [!] command |& command2 # cmd 的错误输出同样被连接到 cmd2 的输入
[time -p] [!] command 2>&1 | command2 # 是上一命令行的展开形式
前一个命令的标准输出被管道连接到后一个命令的标准输入,这种连接是在命令指定的任意重定向操作之前实施的。The standard output of command is connected via a pipe to the standard input of command2. This connection is performed before any redirections specified by the command (see REDIRECTION below).
在管道失败选项没被打开的情况下,管道命令流的返回状态是最后那个命令程序的退出状态。The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. 否则,其返回状态是最后一个以非零状态最初的命令的返回结果,当所有命令正常完成时则返回零。If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully.
如果管道命令流之前有保留字 ! 的话,则其返回状态是前面所述返回状态的逻辑非的结果。If the reserved word ! precedes a pipeline, the exit status of that pipeline is the logical negation of the exit status as described above.
在等待管道命令流中的所有命令终止执行后,shell 才返回该值。The shell waits for all commands in the pipeline to terminate before returning a value.
如果管道命令流之前有保留字 time 的话,相关的执行时间(含用户态时间、核心态时间)会在管道命令流执行结束后报告出来,其中 -p 选项将它们转换成 POSIX 指定的输出格式。变元 TIMEFORMAT 可以被设置成一个格式字符串以便指定如何显示时间信息。If the time reserved word precedes a pipeline, the elapsed as well as user and system time consumed by its execution are reported when the pipeline terminates. The -p option changes the output format to that specified by POSIX. The TIMEFORMAT variable may be set to a format string that specifies how the timing information should be displayed; see the description of TIMEFORMAT under Shell Variables below.
Each command in a pipeline is executed as a separate process (i.e., in a subshell).管道连接的每一个 cmd 都是在一个单独的进程(例如 subshell)中执行。
Lists(执行列表)
执行列表是一个或多个管道的序列,各个管道之间通过 ; & && || 分隔开,可使用 ; & 或 来结束。
使用 `&' 连接的序列,如 pipeA & pipeB 序列,会使得 pipeA 在 background 运行;而使用 `;' 连接的序列,则会顺序执行,即 pipeA 执行完成并返回后,pipeB 才会执行。可以参考如下两个不同的序列。echo 'abc' | less && echo 'def'
echo 'abc' | less & echo 'def'
对于 `&&' 和 `||' 的使用,参见 中的 Errors and Signals and Traps (Oh My!) - Part 1 章节。Compound Commands(复合命令)
可以通过如下的形式将命令组合起来形成「复合命令」。
1. (list)
这里的 list 在 subshell 环境中运行。诸如 variable assignment 和改变 subshell 环境的命令,在 list 执行完成后(即退出 subshell 环境后),都不再生效。
2. { list; }
被称作 group command 组合命令。在当前 shell 环境下运行,只是被组合起来了而已。譬如:cd $some_dir || {
echo "$some_dir does not exists."
exit 1
}
3. ((expression))
此处的 expression 按照 ARITHMETIC EVALUATION 部分的「算数求值」来演算。如果 expression 计算结果非零,则返回真值(同 true 命令返回值一致);如果计算结果为零,则返回假值(同 false 命令返回值一致)。
4. [[ expression ]]
此处的 expression 按照条件表达式的机制进行求值。需要注意的是:
a) 位于[[ 和 ]] 之间的 word 不会被拆分,也不进行路径展开:
Word splitting and pathname expansion are not performed on the words between [[ and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed.
即:诸如 * [a-z] 这样的 pathname expansion 相关的记号,在此处是不被替换的;但是,其他 expantion 都是要做的,譬如 arithmetic expansion 算术扩展。这也使得 [[ expr ]] 和另一个条件求值命令 [ 在算术比较上存在差别,前者会默认按照诸如 0x 前缀将数字识别为 16 进制数,后者则需要显示采用 $((expr)) 的算数求值方式。
b) 另外很重要的两个应用是 glob pattern 和 regexp 匹配。分别采取了 == 和 =~
符号。如下例子。返回值就是是否匹配成功,对于 =~ 而言,如果 RE 表达式出错,那么返回 2 。正则匹配结果、以及 RE group
匹配的结果,存放于 BASH_REMATCH[@] 数组中。url=''
glob_match='*'
glob_match_reverse='mail:*'
regexp_match='(\w+)://([^:/]+)(:([[:digit:]]+))?(/\w+)?'
[[ $url == $glob_match ]]; echo "Matching result: $?" #==> 0
[[ $url != $glob_match_reverse ]]; echo "Matching failed: $?" #==> 0
[[ $url =~ $regexp_match ]] #==> 0
echo $BASH_REMATCH #==>
for part in ${BASH_REMATCH[@]}; do
echo $part
done
# ==>
#
# http
#
# :80
# 80
# /ncr
对于 expression 计算的操作符。存在如下四种。( expr ) # 避免expr受到优先级的影响
expr1 && expr2 # 条件表达式的与或非运算
expr1 || expr2
! expr
5. for name [ [ in [ word ... ] ] ; ] do list ; done
如果 in words 被省略,那么 positional parameters(比如函数参数、命令行参数等等)将被做为 words 列表。
6. for (( expr1 ; expr2 ; expr3 )) ; do list ; done
此处三个表达式都是「算数表达式」。机制同 C 语言的 for 循环类似。
7. select name [ in word ] ; do list ; done
参考 的 Flow Control - Part 2 部分的「菜单选择」。
需要指出,这里的 in word 如果被省略,那么同 for 一样,也是采用 positional parameters 做为 words 列表。
8. case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
word 和 pattern 都会依照 expansion 规则进行扩展,匹配则是按照 glob pattern 形式,逐个逐个 pattern 依次做匹配。每个执行的 list 后可采用 ;; ;& ;;& 三种标记、表明如何继续。分别代表「不再继续匹配其他 pattern」、「直接执行下一个 pattern(无论是否可以匹配)对应的 list」、「继续匹配后续 pattern 并在匹配成功后执行」。
9. if list; then list; [ elif list; then list; ] ... [ else list; ] fi
简单的 if 和 elif else 语句组合,以 fi 结束流程。需要明确的是,每个执行体都是一个命令 list 结构。
10. while list; do list; done
until list; do list; done
反复检查第一个 list 的运行结果,如果为真(while)、或者为假(until)则继续运行。直到第一个 list 求值为假(while)或者真(until)。Coprocesses
这个是 4.0 版本的 bash 中新加入的特性。没看太懂 man 手册上的说明,也没看到某些 Guide 上的描述。故而暂时不关心。Shell Function Definitions
语法形式如下。[ function ] name () compound-command [redirection]
几乎有些不可思议。即关键字 function 和 () 可以是二选一的!即 function 关键字可以省略,此时小括号必须存在;或者存在 function 关键字,此时小括号存在与否无所谓。函数定义时所指定的重定向,会在函数每次被调用时发生,如下。function mfunc
{
echo "${1-"Undefined Arguments."}"
} >> first_arguments
需要注意,一般函数定义,都采取大括号所容纳的命令列表形式,然而理论上任何 compound command 都可以采用。QUOTING
三类 Quoting 形式。\ 或者 'foobar' 或者 "foobar" 三种。
第一种就是 escape character 转义字符了。
第二种单引号形式,可以保证单引号内部都是 literal 值,不会存在进一步的 expansion 或者 quoting 。
第三种双引号形式,除了 $ ` \ 三个字符被「特殊化」之外,其他字符都是 literal 值;$ 和 ` 都是其本来的特殊用法,诸如变量替换、算术运算求值、subshell 运行等等;\ 只有在后继字符是 $ ` \ " 或者换行符时,才是其特殊含义,如下。echo "\."; echo "\$";
根据上述双引号规则,诸如 mvar=* 的 echo "$mvar" 和 echo $mvar 就会存在不同的结果了。这也进一步表明要根据场合,注意是否使用双引号。
需要注意 $'string' 的特殊形式,这个形式会将 string 内的转义字符替换掉,转义字符形式和 ANSI C Standard 的转移序列相同。例如 \n \t \' \" \nnn \xHH 之类,如下。echo $'\n' # 等价于 echo -e '\n' 或者 echo -e "\n"
echo $'\x6f'; echo $'6D'
PARAMETERS
在 bash 中,用于存放 value 的实体被称作 parameter 。这个实体可以是一个 name(变量名字、或者 Array
名称及其索引值)、一个数字(Positional Parameters)、或者是所谓的 Special Parameters 特殊参数。Variable
变量。通过 name 的方式来指定。一个变量存在一个 value 以及零个或多个 attributes 属性值。这些 attributes
可以通过 declare 或者 readonly 之类的内置命令(Bash builtin
command)来指定。一旦一个变量被赋予一个值(或者是 null string 也是被允许的),那么只可以通过 unset 来「注销」。
变量可以通过 name=[value] 的方式来赋值,允许 value 是 null string 的情况。value 会经过
tilde expansion、parameter and variable expansion、command
substitution、arithmetic expansion、quote removal 。如果 variable 存在 integer
属性(declare -i var),那么 value 的求值将会按照 arithmetic expression 的规则。需要注意,pathname expansion 是不被执行的,即诸如 mvar=mvalue* 将会按照 literal value 来传递,而不是根据 pathname 扩展的规则,将星号替换掉。
类似 name=[value] 的 simple assignment statement 也可以使用于 alias declare export readonly local 内置命令中。
诸如 += 的操作符。如下几个例子可说明问题。具体可查看 man 手册。# integer
declare -i mint=10
mint+=20; echo $mint #=> 30
# string
declare mstr='string'
mstr+='_appended'; echo $mstr #=> string_appended
# indexed array
declare -a marr=([0]='index_0' [1]='index_1')
marr+=('index_last-1' 'index_last' [10]='index_10')
echo ${marr[@]} #=> index_0 index_1 index_last-1 index_last index_10
# associated array
declare -A mArr=(['a']='A' ['b']='B')
mArr+=(['g']='G' ['b']='append_to_B')
echo ${mArr[@]} #=> A Bappend_to_B G
Positional Parameters
位置参数。以数字(从1开始的正数)表示的参数(即诸如 $1 $2 ${17} - 如果数字大于一位数则需要大括号)。
不可以采用上面的 simple assigment statement 来给位置参数赋值,但是可以使用内置命令 set 。如下。set -- 'positional_arg_1' 'positional_arg_2' 'positional_arg_3'
就会分别给 $1 以 'positional_arg_1' 值,依此类推。
函数内部的位置参数信息会被重置。即函数内部的位置参数,仅以函数被调用时的参数为准。如果需要使用到 bash 的位置参数(即 bash script 被执行时提供的参数),则需要以参数的形式传入。Special Parameters
$*
$@ # 注意其同`$*'的区别
$#
$?
$$ # 在subshell环境中,返回当前shell而不是subshell的ID值
$0
Arrays
分成 indexed array(索引数组)和 associated array(关联数组)两类。
创建索引数组的方法有两种:marr[1]='value_index_1' 即可创建数组 marr 且索引 1 的值是 value_index_1 字符串;或者显式采取 declare -a marr 的方式,此时也可以一并赋值,如 declare -a marr=([1]='value_index_1') 即可,这种形式被称作 compound assignment statement 复合赋值语句。
创建关联数组则只能够采用 declare -A mArr 的形式(mArr['str1']='value_str1' 的形式会被当作索引数组、而不是关联数组对待,0 是其默认索引值)。一旦创建成功,就可以类似索引数组,采取 mArr[sub]='value_sub' 的形式赋值了。
复合赋值语句。在 declare 创建时、= 赋值语句、+= 赋值语句中,都可以使用。标准形式即 ([sub]=value [sub2]=value2) 依此类推。indexed array 可以没有 [sub]= 的标记,默认从 0 索引开始;associated array 必须存在 `[sub]=' 的确切索引值。
特殊的几个标记。具体含义查看 man 手册。${marr[@]}
${marr[*]} # 明确同${marr[@]}的区别
${#marr[@]} # 等同于${#marr[*]}
${#marr[10]}
${!marr[@]} # key值列表
${!marr[*]}
销毁数组里的某个元素使用 unset arr[sub] 即可;销毁一个数组使用 unset arr 或者 unset arr[@] 或者 unset arr[*] 即可。
需要注意的是,这里的 arr[sub] 会使得 shell 做 pathname expansion 扩展,故而最好用双引号容纳起来。即 unset "arr[sub]" 和 unset "arr[@]"; unset "arr[*]" 形式。
上述创建数组的 -a -A 标记,可以用在 declare local readonly
等命令上。需要指出,readonly(或者 declare 的 -r 标记)将会对某个数组里的每个元素生效,一旦被 readonly
之后,不可再继续赋值,甚至无法被 unset 销毁。每一个函数内使用的 declare 语句,都等同于 local 语句的效果。EXPANSION
参考 里的描述。
按照 expansion 的顺序如下列出。在所有 expansion 进行完毕后,执行 quote removal 。Brace expansion
这个部分只考虑文本上的扩展,并不考察扩展后的语义。因而类似 C 语言的宏一样,符合这种 brace expansion 的形式,就会被扩展开。而且,这个扩展可以嵌套。echo prefix_{a,b,c}_postfix
# => prefix_a_postfix prefix_b_postfix prefix_c_postfix
# Note: echo prefix_{a, b}_postfox 将会返回什么?
Tilde expansion
使用 ~ 符号来做 Tilde expansion 扩展。如下。echo ~
echo ~user_name
其中的 user_name 可以在 /etc/passwd 文件下查找。Shell parameter and variable expansion
echo $SHELL #=> /bin/bash
#
echo "${!SHELL*}" #=> "SHELL SHELLOPTS"
echo "${!SHELL@}" #=> "SHELL" "SHELLOPTS"
echo ${!var[@]} # 其他对于Array的操作这里不重复列出
#
echo ${parameter:-word} # Use default values.
echo ${parameter:=word} # Assign default values.
echo ${parameter:?word} # Display error if null or unset.
echo ${parameter:+word} # Use alternate value.
需要说明,这个小节的 man 手册上还有更多类似如上的 expansion 规则。Command substitution
$(command)
`command`
Arithmetic expansion
$((expr))
Shell parameter 和 variable 都可以做为操作对象,parameter and variable expansion 会在 expr 求值前完成。在 expr 内部,变量可以没有 $ 引用符。而且也不是每个变量都需要指定其 integer 属性,因为默认都是按照 integer 属性做运算。如下。declare -i mint=100
declare -i mint2=070 # 八进制
declare -i mint3=0xf # 十六进制
declare mvar=0xa
echo $(($mint + mint2 + mint3 - mvar)) #=> 100+56+15-10=161
在 bash 中可以使用从 2 - 64 的进制,形式是 base#N ,如果 base# 省略,则默认为 10 进制。采用 0-9 a-z A-Z @ _ 字符集来表示 0 - 63 的数字。比如二进制的 6 可以表示为 2#110 。Process substitution
这个没有搞清楚。今后再关注了。Word splitting
The shell scans the results of parameter expansion, command
substitution, and arithmetic expansion that did not occur within double
quotes for word splitting. 有一个例外,就是 $@ 做为 parameter expansion 类型,依然会被 word splitting 处理。
如果 expansion 没有发生,那么 word splitting 也不会发生。File name expansion
即对 * ? [ 符号做 file name expansion 处理。
隐藏文件(即以 dot 符号开头的文件)不在扩展范围内。除非 shopt -s dotglob 选项被设置。ARITHMETIC EVALUATION
CONDITIONAL EXPRESSIONS
引用 man 手册上的描述。很精准。
Conditional expressions 就是被 [[ 复合命令、或者 test 和 [ 这两个内置命令使用的,用于检测文件属性(是否为文件、文件夹、链接;是否可执行、可读写),比较字符串,或者做算数比较的表达式。
具体可以查看 man 手册上 ^CONDITIONAL EXPRESSIONS 一节的描述。这里引用 中 Flow Control - Part 1 中对条件判断语句的摘录。# 文件 existence 以及类型检查
-e file
-d file
-f file
-L file
# 文件权限检查
-r file
-w file
-x file
# 文件修改时间检查
file1 -nt file2
file1 -ot file2
# 字符串检查,需要注意的是,1000 和 "1000" 都是字符串且相等
-z empty_string # 诸如" "也是空string
-n not_empty_string
string1 = string2
string1 != string2
# 逻辑运算
! expr
expr1 -a expr2
expr1 -o expr2
# 整型运算(可用于类似while等循环递增语句中)
# arg1和arg2应该是整数或者取值为整数的变量
# OP是-eq(等于)-ne(不等于)-lt(小于)-le(小于等于)-gt(大于)-ge(大于等于)之中的一个。
arg1 OP arg2