shell中各种括号的作⽤()、(())、[]、[[]]、{}
⼀、⼩括号,圆括号()
1、单⼩括号 ()
①命令组。括号中的命令将会新开⼀个⼦shell顺序执⾏,所以括号中的变量不能够被脚本余下的部分使⽤。括号中多个命令之间⽤分号隔开,最后⼀个命令可以没有分号,各命令和括号之间不必有空格。
②命令替换。等同于`cmd`,shell扫描⼀遍命令⾏,发现了$(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进位转⼗进制)
③单纯⽤ (( )) 也可重定义变量值,⽐如 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、单中括号 []
①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? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。shell代码
③使⽤[[ ... ]]条件判断结构,⽽不是[ ... ],能够防⽌脚本中的许多逻辑错误。⽐如,&&、||、<;和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。⽐如可以直接使
⽤if [[ $a != 1 && $a != 2 ]], 如果不适⽤双括号, 则为if [ $a -ne 1]
&& [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
④bash把双中括号中的表达式看作⼀个单独的元素,并返回⼀个退出状态码。
例⼦:
if ($i<5) 此处有问题,改为if (($i<5))
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;done
for i in `seq 0 4`;do echo $i;done
for ((i=0;i<5;i++));do echo $i;done
for i in {0..4};do echo $i;done
三、⼤括号、花括号 {}
1、常规⽤法
①⼤括号拓展。(通配(globbing))将对⼤括号中的⽂件名做扩展。在⼤括号中,不允许有空⽩,除⾮这个空⽩被引⽤或转义。第⼀种:对⼤括号中的以逗号分割的⽂件列表进⾏拓展。如 touch {a,b}.txt 结果为a.。第⼆种:对⼤括号中以点点(..)分割的顺序⽂件列表起拓展作⽤,如:touch {a..d}.txt 结果为a. c.
# ls {ex1,ex2}.sh
ex1.sh ex2.sh
# ls {ex{1..3},ex4}.sh
ex1.sh ex2.sh ex3.sh ex4.sh
# ls {ex[1-3],ex4}.sh
ex1.sh ex2.sh ex3.sh ex4.sh
②代码块,⼜被称为内部组,这个结构事实上创建了⼀个匿名函数 。与⼩括号中的命令不同,⼤括号内的命令不会新开⼀个⼦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⽀持通配符,*表⽰零个或多个任意字符,?表⽰仅与⼀个任意字符匹配,[...]表⽰匹配中括号⾥⾯的字符,[!...]表⽰不匹配中括号⾥⾯的字符。
# var=testcase
# echo $var
testcase
# echo ${var%s*e}
testca
# echo $var
testcase
# echo ${var%%s*e}
te
# echo ${var#?e}
stcase
# echo ${var##?e}
stcase
# echo ${var##*e}
# echo ${var##*s}
e
# echo ${var##test}
case
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。
[root@centos ~]# var=/home/centos
[root@centos ~]# echo $var
/home/centos
[root@centos ~]# echo ${var:5}
/centos
[root@centos ~]# echo ${var: -6}
centos
[root@centos ~]# echo ${var:(-6)}
centos
[root@centos ~]# echo ${var:1:4}
home
[root@centos ~]# echo ${var/o/h}
/hhme/centos
[root@centos ~]# 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, 各命令之间⽤分号隔开, 最后⼀个命令后必须有分号, 第⼀条命令和左括号之间必须⽤空格隔开。
对{}和()⽽⾔, 括号中的重定向符只影响该条命令, ⽽括号外的重定向符影响到括号中的所有命令。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论