linux shell 各种括号作用详解()、(())、[]、[[]]、{}

linux shell 各种括号作用详解()、(())、[]、[[]]、{} 一、小括号圆括号1、单小括号 ()①命令组。括号中的命令将会新开一个子shell顺序执行所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开最后一个命令可以没有分号各命令和括号之间不必有空格。②命令替换。等同于cmdshell扫描一遍命令行发现了$(cmd)结构便将$(cmd)中的cmd执行一次得到其标准输出再将此输出放到原来命令。有些shell不支持如tcsh。③用于初始化数组。如array(a b c d)2、双小括号 (( ))①整数扩展。这种扩展计算是整数型的计算不支持浮点型。((exp))结构扩展并计算一个算术表达式的值如果表达式的结果为0那么返回的退出状态码为1或者 是假而一个非零值的表达式所返回的退出状态码将为0或者是true。若是逻辑判断表达式exp为真则为1,假则为0。②只要括号中的运算符、表达式符合C语言运算规则都可用在$((exp))中甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时输出结果全都自动转化成了十进制。如echo $((16#5f)) 结果为95 (16进位转十进制)③单纯用 (( )) 也可重定义变量值比如 a5; ((a)) 可将 $a 重定义为6④常用于算术运算比较双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则,比如可以直接使用for((i0;i5;i)), 如果不使用双括号, 则为for i in seq 0 4或者for i in {0..4}。再如可以直接使用if (($i5)), 如果不使用双括号, 则为if [ $i -lt 5 ]。二、中括号方括号[]1、单中括号 []①bash 的内部命令[和test是等同的。如果我们不用绝对路径指明通常我们用的都是bash自带的命令。if/test结构中的左中括号是调用test的命令标识右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试并且根据比较的结果来返回一个退出状态码。if/test结构中并不是必须右中括号但是新版的Bash中要求必须这样。②Test和[]中可用的比较运算符只有和!两者都是用于字符串比较的不可用于整数比较整数比较只能使用-eq-gt这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用对于字符串比较可以使用转义形式如果比较ab和bc[ ab \ bc ]结果为真也就是返回状态为0。[ ]中的逻辑与和逻辑或使用-a 和-o 表示。且[]前后都有空格。③字符范围。用作正则表达式的一部分描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。④在一个array 结构的上下文中中括号用来引用数组中每个元素的编号。2、双中括号[[ ]]①[[是 bash 程序语言的关键字。并不是一个命令[[ ]] 结构比[ ]结构更加通用。在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割但是会发生参数扩展和命令替换。②支持字符串的模式匹配使用~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式而不仅仅是一个字符串比如[[ hello hell? ]]结果为真。[[ ]] 中匹配字符串或通配符不需要引号。③使用[[ ... ]]条件判断结构而不是[ ... ]能够防止脚本中的许多逻辑错误。比如、||、和 操作符能够正常存在于[[ ]]条件判断结构中但是如果出现在[ ]结构中的话会报错。比如可以直接使用if [[ $a ! 1 $a ! 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] [ $a ! 2 ]或者if [ $a -ne 1 -a $a ! 2 ]。④bash把双中括号中的表达式看作一个单独的元素并返回一个退出状态码。例子[cpp]view plain copyif ($i5)if [ $i -lt 5 ]if [ $a -ne 1 -a $a ! 2 ]if [ $a -ne 1] [ $a ! 2 ]if [[ $a ! 1 $a ! 2 ]]for i in $(seq 0 4);do echo $i;donefor i in seq 0 4;do echo $i;donefor ((i0;i5;i));do echo $i;donefor i in {0..4};do echo $i;done三、大括号、花括号 {}1、常规用法①大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。在大括号中不允许有空白除非这个空白被引用或转义。第一种对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为a.txt b.txt。第二种对大括号中以点点..分割的顺序文件列表起拓展作用如touch {a..d}.txt 结果为a.txt b.txt c.txt d.txt例如:[rootiz2ze46xi6pjjj69ailg9lz ttt]# touch test{0..5}.txt [rootiz2ze46xi6pjjj69ailg9lz ttt]# ls test0.txt test1.txt test2.txt test3.txt test4.txt test5.txt [rootiz2ze46xi6pjjj69ailg9lz ttt]# echo str{b..d} strb strc strd [rootiz2ze46xi6pjjj69ailg9lz ttt]# echo str{b,d} strb strd②代码块又被称为内部组这个结构事实上创建了一个匿名函数 。与小括号中的命令不同大括号内的命令不会新开一个子shell运行即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开最后一个也必须有分号。{}的第一个命令和左括号之间必须要有一个空格。{}也可以用于多行注释作为函数包起来只是不调用即可。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支持通配符*表示零个或多个任意字符?表示仅与一个任意字符匹配[...]表示匹配中括号里面的字符[!...]表示不匹配中括号里面的字符。[cpp]view plain copy# vartestcase# echo $vartestcase# echo ${var%s*e}testca# echo $vartestcase# echo ${var%%s*e}te# echo ${var#?e}stcase# echo ${var##?e}stcase# echo ${var##*e}# echo ${var##*s}e# echo ${var##test}case4、字符串提取和替换${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。[html]view plain copy[rootcentos ~]# var/home/centos[rootcentos ~]# echo $var/home/centos[rootcentos ~]# echo ${var:5}/centos[rootcentos ~]# echo ${var: -6}centos[rootcentos ~]# echo ${var:(-6)}centos[rootcentos ~]# echo ${var:1:4}home[rootcentos ~]# echo ${var/o/h}/hhme/centos[rootcentos ~]# echo ${var//o/h}/hhme/cenths四、符号$后的括号1${a} 变量a的值, 在不引起歧义的情况下可以省略大括号。2$(cmd) 命令替换和cmd效果相同结果为shell命令cmd的输过某些Shell版本不支持$()形式的命令替换, 如tcsh。3$((expression)) 和exprexpression效果相同, 计算数学表达式exp的数值, 其中exp只要符合C语言的运算规则即可, 甚至三目运算符和逻辑表达式都可以计算。五、使用1、多条命令执行1单小括号(cmd1;cmd2;cmd3) 新开一个子shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号。2单大括号{ cmd1;cmd2;cmd3;} 在当前shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开。对{}和()而言, 括号中的重定向符只影响该条命令 而括号外的重定向符影响到括号中的所有命令。例如:#!/bin/bash str1test1 str2Test1 num133 num24 ###################string complare######### #1 [] use if [ $str1 $str2 ] then echo #1 ${str1} equals to ${str2} else echo #1 ${str1} not e2 $str2 fi #2 [] use ! if [ $str1 ! $str2 ] then echo #2 ${str1} not equals to ${str2} else echo #2 ${str1} eq2 $str2 fi #3 [] use \ (注意字符串之间不能有空格) if [ ${str1}\${str2} ] then echo #3 ${str1} less than ${str2} else echo #3 ${str1} eq2 or grater than $str2 fi #4 [[]] use if [[ $str1 $str2 ]] then echo #4 ${str1} less than ${str2} else echo #4 ${str1} eq2 or grater than $str2 fi #################### number complare ############################ #1 [] use -lt.-gt,-ge if [ $num1 -lt ${num2} ] then echo ${num1} less than ${num2} else echo ${num1} eq2 or grater than $num2 fi #2 [] use \ is complare as string (错误的示范不能在[]中使用转义比较数字会当成字符串比较) if [ $num1 \ ${num2} ] then echo ${num1} less than ${num2} else echo ${num1} eq2 or grater than $num2 fi #3 (()) use if (( $num1 ${num2} )) then echo ${num1} less than ${num2} else echo ${num1} eq2 or grater than $num2 fi #####################(()) use to number -*/ ########################### echo ############# (()) use ro number -*/% ############## echo $(($num1 $num2)) echo $(($num1 - $num2)) echo $(($num1 * $num2)) echo $(($num1 / $num2)) echo $(($num1 % $num2)) ####################### () ################### echo ############# \$() use like \\ ################## echo which pwd echo $(which pwd) ##################### \${} to get variables ######################### echo ################## \${var} is like \$var ################ echo ${str1} echo $str1运行结果:#1 test1 not e2 Test1 #2 test1 not equals to Test1 #3 test1 less than Test1 #4 test1 less than Test1 33 eq2 or grater than 4 33 less than 4 33 eq2 or grater than 4 ############# (()) use ro number -*/% ############## 37 29 132 8 1 ############# $() use like ################## /usr/bin/pwd /usr/bin/pwd ################## ${var} is like $var ################ test1 test1总结:(1)$(cmd)与··(键盘上1左边的~)一样都是命令替换可以将执行结果提取出来(2)[]使用的时候[ ]前后都必须有空格且两个字符或数字之间的比较符左右也必须有空格。(3) []是test的另一种形式[]中间只能使用 和 ! 比较字符串如果使用 、需要进行转义\。[]中间如果比较数字需要用 -lt 等符号不能使用\比较数字会当成字符串处理。(4)[[]]可用于处理逻辑命令也可以用于处理字符串是否相等且使用、不用转义符.(5)(())可用于比较数字且不用转义而且也可以用于数字计算比较的时候也是用普通的,。(())计算的时候运算符与数字之间不能有空格例如: sum$(($sum4))(6)字符串比较 用[],与普通的,,,!符号如果使用,需要转义;或者使用[[]]比较字符串也是用普通符号不用转义数字比较用[]的时候用-lt,-gt等符号不能使用\(因为会当成字符串处理);或者用(())比较数字用普通符号不用转义(7)可以将$理解为取变量的符号$var 或者 ${} 在不影响语义的情况下可以省去{},但是最好写上{}。例如:testXXX.$testWWWW.这时候就必须加上{}变为${test}WWWW