这篇文章上次修改于 2262 天前,可能其部分内容已经发生变化,如有疑问可询问作者。 # []和[[]] 在写Shell脚本的时候,经常在写条件判断语句时不知道该用`[]` 还是` [[]]`,首先我们来看他们的类别: ``` $type [ [[ test [ is a shell builtin [[ is a shell keyword test is a shell builtin ``` `[` 和`test` 是 Shell 的内部命令,而`[[`是Shell的关键字。 ``` $test -f settings.py && echo True True $[ -f settings.py ] && echo True True ``` [ 和test 是相等的。 ``` $[ 2 < 1 ] && echo True || echo False True $[[ 2 < 1 ]] && echo True || echo False False ``` 既然是命令, 它就和参数组合为一体被 shell 解释,那样比如 ">" "<" 就被 shell 解释为重定向符号了。关键字却不这样。 ``` x=1 y=1 $[ $x == 1 && $y == 1 ] && echo True || echo False -bash: [: missing `]' False $[[ $x == 1 && $y == 1 ]] && echo True || echo False True $[ $x == 1 -a $y == 1 ] && echo True || echo False True ``` 在`[[`中使用`&&`和`||`表示逻辑与和逻辑或。`[`中使用`-a` 和`-o` 表示逻辑与和逻辑或。 ``` $[[ 'abcd' == a*d ]] && echo True || echo False True $[ 'abcd' == a*d ] && echo True || echo False False ``` `[[`支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。 ## 小结1: 使用[[ ... ]]条件判断结构,而不是[ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中, 但是如果出现在[ ]结构中的话,会报错。比如可以直接使用`if [[ $a != 1 && $a != 2 ]]` 如果不使用双括号, 则为`if [ $a -ne 1] && [ $a != 2 ]`或者`if [ $a -ne 1 -a $a != 2 ]` bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。 ``` $[ !(pip list | grep pip) ] && echo True || echo False -bash: [: too many arguments False $[[ !(pip list | grep pip) ]] && echo True || echo False True ``` # $( ) 与`` (反引号) 在 bash shell 中,`$( )`与 ` `` ` (反引号) 都可用做命令替换用。 例如 `version=$(uname -r)`和`` version=`uname -r` ``都可以是version得到内核的版本号 各自的优缺点: 1. ` `` ` 基本上可用在全部的 unix shell 中使用,若写成 shell script ,其移植性比较高,但反单引号容易打错或看错。 2. `$()`并不是所有shell都支持。 `${ }`用于变量替换。一般情况下,`$var `与`${var} `并没有什么不一样,但是用 `${ }` 会比较精确的界定变量名称的范围。 `${ }`的模式匹配功能: 1. `# `是去掉左边(在键盘上#在$之左边) 2. `%` 是去掉右边(在键盘上%在$之右边) 3. `#`和`%`中的单一符号是最小匹配,两个相同符号是最大匹配。 `${variable#pattern}`:shell在variable中查找,看它是否以给定的模式pattern开始,如果是,就从命令行把variable中的内容去掉左边最短的匹配模式 `${variable##pattern}`:shell在variable中查找,看它是否以给定的模式pattern开始,如果是,就从命令行把variable中的内容去掉左边最长的匹配模式 `${variable%pattern}`:shell在variable中查找,看它是否以给定的模式pattern结尾,如果是,就从命令行把variable中的内容去掉右边最短的匹配模式 `${variable%%pattern}`:shell在variable中查找,看它是否以给定的模式pattern结尾,如果是,就从命令行把variable中的内容去掉右边最长的匹配模式 这四种模式中都不会改变variable的值,其中,只有在pattern中使用了*匹配符号时,%和%%,#和##才有区别。结构中的pattern支持通配符,*表示零个或多个任意字符,?表示仅与一个任意字符匹配,[...]表示匹配中括号里面的字符,[!...]表示不匹配中括号里面的字符。 # $[] 和 $(()) `$[]`和`$(())`是一样的,都是进行数学运算的。支持+ - * / %(“加、减、乘、除、取模”)。但是注意,bash只能作整数运算,对于浮点数是当作字符串处理的。 ``` $ a=5; b=7; c=2 $ echo $(( a+b*c )) 19 $ echo $(( (a+b)/c )) 6 $ echo $(( (a*b)%c)) 1 ``` 在` $(( ))` 中的变量名称,可于其前面加` $` 符号来替换,也可以不用,如: `$(( $a + $b * $c)) `也可得到 19 的结果 此外,`$(( )) `还可作不同进位(如二进制、八进位、十六进制)运算,只是,输出结果皆为十进制而已: `echo $((16#2a)) `结果为 42 (16进位转十进制) # (( ))及[[ ]] 分别是`[ ]`的针对数学比较表达式和字符串表达式的加强版。 其中 `[[ ]]`中增加模式匹配特效; `(( ))`不需要再将表达式里面的大小于符号转义,除了可以使用标准的数学运算符外,还增加了以下符号: ![20180516104157725.png](/usr/uploads/2018/08/931217852.png) ##小结2: 数学运算使用`(())`,字符串运算使用`[[]]` # 参考 - http://blog.csdn.net/taiyang1987912/article/details/39551385 - http://blog.csdn.net/yongan1006/article/details/7195303 - https://www.shellcheck.net/
没有评论