注释: []、[[]]、()、(())、{} 在不同解释器中的含义 #num1 1.[] 和 test 两者是一样的,在命令行里test expr和[ expr ]的效果相同 test的三个基本作用是判断文件、判断字符串、判断整数,支持使用 "与或非" 将表达式连接起来 test和[]中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq,-gt这种形式 无论是字符串比较还是整数比较都不支持大于号小于号,如果实在想用,对于字符串比较可以使用转义形式,如果比较"ab"和"bc":[ ab \< bc ],结果为真,也就是返回状态为0;[ ]中的逻辑与和逻辑或使用-a 和-o 表示 []中有用到变量则使用 "$var" 或者 ${var} 的形式 1) 字符运算 == != 2) 数值运算 -gt -ge -eq -ne -le -lt 3) 文件运算 文件属性: -r -w -x -u -g -G -s -N -k 文件类型: -e -f -d -l -b -c -S -p 两文件之间比较: -nt -ot -ef(是否为同一文件,两个文件是否均指向同一个分区上的同一个inode) [ -e file ] 4) 字符运算 -z -n = == (=、==在test中等价,但=可移植性更好) != >(字母顺序判断) < [ -n string ] [ -z string ] [ ! -n string ] [ string ] (与 [ -z string ] 相同) [ ! string ] [ a > c ] 5) 布尔值运算 -a -o [ string1 == string2 -o string1 == string3 ] 6) 逻辑运算 && || (-a -o 只能在test或[]中使用, && || 只能在[[ ]]中使用) !(取反) [ $a -ne 1] && [ $a != 2 ] ....(未完待续) !!注意!! 使用[]和[[]]的时候不要吝啬空格,每一项两边都要有空格 [] 不支持算术扩展 (),用于改变表达式的优先级,为了防止被shell解析,应该加上反斜线转义\( \) 2.[] 用作正则表达式的一部分,描述一个匹配的字符范围;作为test用途的中括号内不能使用正则 在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号 1) 字符范围 [a-z] [0-9] 例: 如果你的当前目录下有a1-a9九个文件,你可以用a[1-9]来替代这九个文件;有点需要注意,你不能用a[1-20]来代替a1-a20,必须要a[1-9] a1[0-9] a20 2) 数组 arry[] 3) $(()) 的另一种表现(过去形式,现在已经不建议使用) $[] ################################################################# #num2 1.[[ ]] 方括号 [] 的加强版,常用于字符串的比较,主要用于条件测试 [[ ]]中的表达式可以使用&&, ||, <, >等C语言语法;[[ ]] 支持进行算术扩展,支持bash中的通配符扩展 在[[和]]之间的所有的字符都不会被文件扩展或是标记分割,但是会有参数引用和命令替换(bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码) 支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式;字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真 1) 逻辑运算 && || [[ $a != 1 && $a != 2 ]] 2) 字符运算 = != -n -z 3) 数值运算 >、>=、<、<=、==、!= -gt -ge -eq -ne -le -lt 4) bash通配符或字符串 "*" "?" "[...]" [[ hest = h??t ]] , [[ hest = h*t ]] 5) 正则表达式 =~ [[ abc =~ aa.* ]] [[ abc =~ aa* ]] !!注意!! 使用[]和[[]]的时候不要吝啬空格,每一项两边都要有空格 [[ "a" != 1 && "a" != 2 ]] 判断结果不正常,[[ $a != 1 && $a != 2 ]] 能正常判断 如 [ 2 \< 10 ] [[ 2 < 10 ]] 最好不使用; 使用算术扩展最好用 (( 99+1 == 100 )) ,而不要使用[[ 99+1 -eq 100 ]] [[ ]]不再支持"-a"和"-o" 除了模式匹配和正则表达式匹配时需要使用[[]],其余时候建议使用[ ] ###################################################################### #num3 1.() (单小括号) 命令组: 括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用;括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格 命令替换: 等同于`cmd`,shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令;有些shell不支持,如tcsh 初始化数组: 如 array=(a b c d) 进程代入,可以把命令的执行结果当成文件一样读入 1) 命令替换 echo $(ls $(pwd) | egrep 'txt$') 2) 进程带入 <()和 >() paste <(cut -t2 file1) <(cut -t1 file1),和管道差不多,但是支持多个输入 !!注意!! ()只是对一串命令重新开一个子shell进行执行 ()和{}都是把一串的命令放在括号里面,并且命令之间用";"号隔开 ()最后一个命令可以不用分号 ()里的各命令不必和括号有空格 ()和{}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令 ################################################################################## #num4 1.(( )) (双小括号) 整数扩展: 这种扩展计算是整数型的计算,不支持浮点型;((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者 是"假",而一个非零值的表达式所返回的退出状态码将为0,或者是"true";若是逻辑判断,表达式exp为真则为1,假则为0 只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,甚至是三目运算符;作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制;如: echo $((16#5f)) 结果为95 (16进位转十进制) 省去$符号的算术运算: 单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6;括号内支持多个表达式用逗号分开; 只要括号中的表达式符合C语言运算规则,比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in `seq 0 4`或者for i in {0..4};再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ] 常用于算术运算比较,双括号中的变量可以不使用$符号前缀 1) 数值运算 + - * / % 2) 数值比较 > >= < <= == != 3) 算术扩展 (( 99+1 <= 101 )) !!注意!! $(( ))将运算表达式提取出来,可以赋值给变量,例:a=$((5+7)),[ $((a+0)) -le 8 ]; 但是和(( ))不同,$(())不能直接$((b++)),如下: b=1;echo $((++b))这时b等于2,显示的也是2,b=1;echo $((b++))这时b等于2,显示的是1 ############################################################################### #num5 1.{ } (单大括号) 1) 大括号拓展: 对大括号中的文件名做扩展 在大括号中,不允许有空白,除非这个空白被引用或转义 第一种: 对大括号中的以逗号分割的文件列表进行拓展 ls {ex1,ex3,ex6}.sh 第二种:对大括号中以点点'..'分割的顺序文件列表起拓展作用(或者[1-5]) ls {ex{1..3},ex4}.sh ls {ex[1-3],ex4}.sh 2) 特殊替换——${var:-string},${var:+string},${var:=string},${var:?string} ${var:-string}和${var:=string}:若变量var为空,则用在命令行中用string来替换${var:-string},否则变量var不为空时,则用变量var的值来替换${var:-string};对于${var:=string}的替换规则和${var:-string}是一样的,所不同之处是${var:=string}若var为空时,用string替换${var:=string}的同时,把string赋给变量var: ${var:=string}很常用的一种用法是,判断某个变量是否赋值,没有的话则给它赋上一个默认值 ${var:+string}的替换规则和上面的相反,即只有当var不是空的时候才替换成string,若var为空时则不替换或者说是替换成变量 var的值,即空值;(因为变量var此时为空,所以这两种说法是等价的) ${var:?string}替换规则为:若变量var不为空,则用变量var的值来替换${var:?string};若变量var为空,则把string输出到标准错误中,并从脚本中退出;我们可利用此特性来检查是否设置了变量的值 补充扩展:在上面这五种替换结构中string不一定是常值的,可用另外一个变量的值或是一种命令的输出 3) 模式匹配替换——${var%pattern},${var%%pattern},${var#pattern},${var##pattern} # 是去掉左边(在键盘上#在$之左边);% 是去掉右边(在键盘上%在$之右边);#和%中的单一符号是最小匹配,两个相同符号是最大匹配; 第一种: ${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支持通配符,*表示零个或多个任意字符,?表示仅与一个任意字符匹配,[...]表示匹配中括号里面的字符,[!...]表示不匹配中括号里面的字符; 4) 字符串提取和替换——${var:num},${var:num1:num2},${var/pattern/pattern},${var//pattern/pattern} 第一种: ${var:num},这种模式时,shell在var中提取第num个字符到末尾的所有字符;若num为正数,从左边0处开始;若num为负数,从右边开始提取字串,但必须使用在冒号后面加空格或一个数字或整个num加上括号,如${var: -2}、${var:1-3}或${var:(-2)}; 第二种: ${var:num1:num2},num1是位置,num2是长度;表示从$var字符串的第$num1个位置开始提取长度为$num2的子串;不能为负数; 第三种: ${var/pattern/pattern}表示将var字符串的第一个匹配的pattern替换为另一个pattern; 第四种: ${var//pattern/pattern}表示将var字符串中的所有能匹配的pattern替换为另一个pattern; !!注意!! 对{}和()而言, 括号中的重定向符只影响该条命令, 而括号外的重定向符影响到括号中的所有命令 创建匿名函数(不会新开进程),{}对一串命令在当前shell执行,括号内变量余下仍可使用 {}最后一个命令要用分号,命令之间用";"号隔开,{}的第一个命令和左括号之间必须要有一个空格 ${a} 变量a的值, 在变量与字符串之间没有歧义的情况下可以省略大括号 代码块,又被称为内部组,这个结构事实上创建了一个匿名函数