Thursday, November 3, 2011

bash 条件表达式 'test' '[' '[['

一直以来对test、[、和[[没有深研究,今天代码被挑刺了,就在这个几点上,因此决定好好在研究一下,翻了几个blog,同时又看了Bash Reference,本文的文字主要摘自Bash Reference,外加自己的一点解释、以及例子等。

首先看到6.4 Bash Conditional Expressions

Bash Conditional Expressions


开头说到条件表达式通常用于 [[ compound command and the test and [builtin commands.

Expressions may be unary or binary. Unary expressions are often used to examine the status of a file. There are string operators and numeric comparison operators as well(用于检查文件的status,以及字符串操作和算术比较). If the fileargument to one of the primaries is of the form/dev/fd/N, then file descriptor N is checked. If the fileargument to one of the primaries is one of/dev/stdin,/dev/stdout, or/dev/stderr, file descriptor 0, 1, or 2, respectively, is checked.

When used with ‘[[’, The ‘<’ and ‘>’ operators sort lexicographically using the current locale(此时基于字典序).

Unless otherwise specified, primaries that operate on files follow symbolic links and operate on the target of the link, rather than the link itself.

文件
-a file
True if file exists.
-b file
True if file exists and is a block special file.
-c file
True if file exists and is a character special file.
-d file
True if file exists and is a directory.
-e file
True if file exists.
-f file
True if file exists and is a regular file.
-g file
True if file exists and its set-group-id bit is set.
-h file
True if file exists and is a symbolic link.
-k file
True if file exists and its "sticky" bit is set.
-p file
True if file exists and is a named pipe (FIFO).
-r file
True if file exists and is readable.
-s file
True if file exists and has a size greater than zero.
-t fd
True if file descriptor fd is open and refers to a terminal.
-u file
True if file exists and its set-user-id bit is set.
-w file
True if file exists and is writable.
-x file
True if file exists and is executable.
-O file
True if file exists and is owned by the effective user id.
-G file
True if file exists and is owned by the effective group id.
-L file
True if file exists and is a symbolic link.
-S file
True if file exists and is a socket.
-N file
True if file exists and has been modified since it was last read.
file1 -nt file2
True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.
file1 -ot file2
True if file1 is older than file2, or if file2 exists and file1 does not.
file1 -ef file2
True if file1 and file2 refer to the same device and inode numbers.
操作符
-o optname
True if shell option optnameis enabled. The list of options appears in the description of the-ooption to the set builtin (see The Set Builtin).
字符串
-z string
True if the length of string is zero.
-n string
string
True if the length of string is non-zero.
string1 == string2
string1 = string2
True if the strings are equal.=’ should be used with the test command for posix conformance.
string1 != string2
True if the strings are not equal.
string1 < string2
True if string1 sorts before string2 lexicographically.
string1 > string2
True if string1 sorts after string2 lexicographically.
算术
arg1 OP arg2
OPis one of ‘-eq’, ‘-ne’, ‘-lt’, ‘-le’, ‘-gt’, or ‘-ge
’. These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to arg2, respectively. Arg1 and arg2 may be positive or negative integers(必须是整数).
下面就依次来看看'[['和'test' '['

先看'[['


位于3.2.4.2 Conditional Constructs

[[...]]

          [[ expression ]]

Return a status of 0 or 1 depending on the evaluation of the conditional expression expression. Expressions are composed of the primaries described below in Bash Conditional Expressions. Word splitting and filename expansion are not performed on the words between the ‘[[’ and ‘]]’; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed. Conditional operators such as ‘-f’ must be unquoted to be recognized as primaries.

When used with ‘[[’, The ‘<’ and ‘>’ operators sort lexicographically using the current locale.

When the ‘==’ and ‘!=’ operators are used, the string to the right of the operator is considered a pattern and matched according to the rules described below in Pattern Matching. If the shell option nocasematch (see the description of shopt in The Shopt Builtin) is enabled, the match is performed without regard to the case of alphabetic characters. The return value is 0 if the string matches (‘==’) or does not match (‘!=’)the pattern, and 1 otherwise. Any part of the pattern may be quoted to force it to be matched as a string.

An additional binary operator, ‘=~’, is available, with the same precedence as ‘==’ and ‘!=’. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex3)). The return value is 0 if the string matches the pattern, and 1 otherwise. If the regular expression is syntactically incorrect, the conditional expression's return value is 2. If the shell option nocasematch (see the description of shopt in The Shopt Builtin) is enabled, the match is performed without regard to the case of alphabetic characters. Any part of the pattern may be quoted to force it to be matched as a string. Substrings matched by parenthesized subexpressions within the regular expression are saved in the array variable BASH_REMATCH. The element of BASH_REMATCH with index 0 is the portion of the string matching the entire regular expression. The element of BASH_REMATCH with index n is the portion of the string matching the nth parenthesized subexpression.

Expressions may be combined using the following operators, listed in decreasing order of precedence:

( expression )
Returns the value of expression. This may be used to override the normal precedence of operators.
! expression
True if expression is false.
expression1 && expression2
True if both expression1 and expression2 are true.
expression1 || expression2
True if either expression1 or expression2 is true.
The && and || operators do not evaluate expression2 if the value of expression1 is sufficient to determine the return value of the entire conditional expression.


再来看 'test'和'['


位于4.1 Bourne Shell Builtins

test和[是等价的,不过用的时候形式不一样如if  test expression,和if [ expression ]

Evaluate a conditional expression expr. Each operator and operand must be a separate argument. Expressions are composed of the primaries described below in Bash Conditional Expressions. testdoes not accept any options, nor does it accept and ignore an argument of--as signifying the end of options.When the [ form is used, the last argument to the command must be a ].Expressions may be combined using the following operators, listed in decreasing order of precedence. The evaluation depends on the number of arguments; see below.
! expr
True if expr is false.
( expr )
Returns the value of expr. This may be used to override the normal precedence of operators.
expr1 -a expr2
True if both expr1 and expr2 are true.
expr1 -o expr2
True if either expr1 or expr2 is true.
The test and [ builtins evaluate conditional expressions using a set of rules based on the number of arguments.这里把test其实是一个函数,根据不同的参数个数来判断出结果

0 arguments
The expression is false.
1 argument
The expression is true if and only if the argument is not null.
2 arguments
If the first argument is ‘!’, the expression is true if and only if the second argument is null. If the first argument is one of the unary conditional operators (see Bash Conditional Expressions), the expression is true if the unary test is true. If the first argument is not a valid unary operator, the expression is false.
3 arguments
If the second argument is one of the binary conditional operators (see Bash Conditional Expressions), the result of the expression is the result of the binary test using the first and third arguments as operands. The ‘-a’ and ‘-o’ operators are considered binary operators when there are three arguments. If the first argument is ‘!’, the value is the negation of the two-argument test using the second and third arguments. If the first argument is exactly ‘(’ and the third argument is exactly ‘)’, the result is the one-argument test of the second argument. Otherwise, the expression is false.
4 arguments
If the first argument is ‘!’, the result is the negation of the three-argument expression composed of the remaining arguments. Otherwise, the expression is parsed and evaluated according to precedence using the rules listed above.
5 or more arguments
The expression is parsed and evaluated according to precedence using the rules listed above.

[ ]和[[ ]]的区别


这两者的大部分功能都是一样的,但是后者[[]]比前者[]更加完善。

1.[[有扩展功能,通配符匹配(==和!=)和正则表达式匹配(=~),这在上面讲解[[的时候专门有两个段落说明

==和!=的右操作符为pattern进行3.5.8.1 Pattern Matching

这个时候,假如要比较的右侧字符串中有特殊字符如*,则需要用"引起来

[shell]
$ [[ "GFW" == G*W ]]
$ echo $?
0
$ [[ "GFW" == "G*W" ]]
$ echo $?
1
[/shell]

=~的右操作符作为正则表达式,这里正则的引号可用可不用

[shell]
$ [[ "GFW" =~ "G*W" ]]
$ echo $?
0
$ [[ "GFW" =~ 'G*W' ]]
$ echo $?
0
$ [[ "GFW" =~ G*W ]]
$ echo $?
0
[/shell]

2.[的二元操作符的右操作符(通常是某变量)不能为空(null),当然可以通过加引号来解决

首先使用[如下:

[shell]
$ [ "GFW" == $fuck  ]
bash: [: GFW: unary operator expected
[/shell]

就会报错,而加了引号就没有问题了,这个时候当作一个空字符串处理

[shell]
$ [ "GFW" == "$fuck" ]
$ echo $?
1
[/shell]

假如是使用[[就不存在该问题,加不加引号都ok,如下:

[shell]
$ [[ "GFW" == $fuck ]]
$ echo $?
1
$ [[ "GFW" == "$fuck" ]]
$ echo $?
1
[/shell]

另外还有个(( ))


((...))

          (( expression ))

The arithmetic expression is evaluated according to the rules described below (see Shell Arithmetic). If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to
          let "expression"

See Bash Builtins, for a full description of the let builtin.

Shell Arithmetic如下

The shell allows arithmetic expressions to be evaluated, as one of the shell expansions or by the letand the

-ioption to the declarebuiltins.

Evaluation is done in fixed-width integers with no check for overflow, though division by 0 is trapped and flagged as an error. The operators and their precedence, associativity, and values are the same as in the C language. The following list of operators is grouped into levels of equal-precedence operators. The levels are listed in order of decreasing precedence.

id++ id--
variable post-increment and post-decrement
++id --id
variable pre-increment and pre-decrement
- +
unary minus and plus
! ~
logical and bitwise negation
**
exponentiation
* / %
multiplication, division, remainder
+ -
addition, subtraction
<< >>
left and right bitwise shifts
<= >= < >
comparison
== !=
equality and inequality
&
bitwise AND
^
bitwise exclusive OR
|
bitwise OR
&&
logical AND
||
logical OR
expr ? expr : expr
conditional operator
= *= /= %= += -= <<= >>= &= ^= |=
assignment
expr1 , expr2
comma
Shell variables are allowed as operands; parameter expansion is performed before the expression is evaluated. Within an expression, shell variables may also be referenced by name without using the parameter expansion syntax. A shell variable that is null or unset evaluates to 0 when referenced by name without using the parameter expansion syntax. The value of a variable is evaluated as an arithmetic expression when it is referenced, or when a variable which has been given the integerattribute using ‘declare -i’ is assigned a value. A null value evaluates to 0. A shell variable need not have its integer attribute turned on to be used in an expression.

Constants with a leading 0 are interpreted as octal numbers. A leading ‘0x’ or ‘0X’ denotes hexadecimal. Otherwise, numbers take the form [base#]n, where base is a decimal number between 2 and 64 representing the arithmetic base, and n is a number in that base. If base#is omitted, then base 10 is used. The digits greater than 9 are represented by the lowercase letters, the uppercase letters, ‘@’, and ‘_’, in that order. If base is less than or equal to 36, lowercase and uppercase letters may be used interchangeably to represent numbers between 10 and 35.

Operators are evaluated in order of precedence. Sub-expressions in parentheses are evaluated first and may override the precedence rules above.

No comments:

Post a Comment