shell之小括号()和花括号{}用法

shell里的小括号,大括号结构和有括号的变量,命令的用法如下:

1.${var} 
2.$(cmd) 
3.()和{} 
4.${var:-string},${var:+string},${var:=string},${var:?string} 
5.$((exp)) 
6.$(var%pattern),$(var%%pattern),$(var#pattern),$(var##pattern)

1、单小括号()
(1)、命令组:$(cmd;cmd2;cmd3) 括号中的命令将会新开一个子shell顺序执行,括号中多个命令之间分号分隔,最后一个命令可以无分号
(2)、命令替换:$(cmd) 等同于`cmd`
(3)、用户初始化数组:array=(a b c d)

2、双小括号(())
(1)、整数扩展:扩展计算是整数型的计算,不支持浮点型。
(2)、只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,甚至是三目运算符
(3)、单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6
(4)、常用于算术运算比较:
如 for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in `seq 0 4`或者for i in {0..4}。再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ]

花括号

3、花括号
(1)、大括号扩展:
如 touch {a,b}.txt 结果为a.txt b.txt。第二种:对大括号中以点点(..)分割的顺序文件列表起拓展作用,如:touch {a..d}.txt 结果为a.txt b.txt c.txt d.txt
(2)、几种特殊的替换结构:
${var:-string}、${var:+string}、${var:=string}、${var:?string}
1、若变量var为空,则用在命令行中用string来替换${var:-string},否则变量var不为空时,则用变量var的值来替换${var:-string}
如: 
echo $newvar
echo ${newvar:-a} 
a 
echo $newvar      【变量newvar的值仍然是空,故上一命令行中${newvar:-a}被替换成了a】

newvar=b 
echo ${newvar:-a} 【变量newvar的值不为空时,故此命令行中的${newvar:-b}被替换为$newvar,即b】
b 

2、对于${var:=string}的替换规则和${var:-string}是一样的,所不同之处是${var:=string}若var为空时,用string替换${var:=string}的同时,把string赋给变量var:
【${var:=string}很常用的一种用法是,判断某个变量是否赋值,没有的话则给它赋上一个默认值】
echo $newvar
echo ${newvar:=a} 
a 
echo $newvar      【变量newvar被赋值为a,同时${newvar:=a}被替换成a】
a 

echo ${newvar:=b} 【变量newvar不为空(其值已被赋为a),则${newvar:=b}被替换为newvar的值(即a)】 
a 
echo $newvar 
a

3、${var:+string}的替换规则和上面的相反,即只有当var不是空的时候才替换成string,若var为空时则不替换或者说是替换成变量 var的值,即空值。(因为变量var此时为空,所以这两种说法是等价的) 
echo $newvar 
a 
echo ${newvar:+b} 
b 
echo $newvar 
a 

newvar= 
echo ${newvar:+b}


4、${var:?string}替换规则为:若变量var不为空,则用变量var的值来替换${var:?string};若变量var为空,则把string输出到标准错误中,并从脚本中退出。我们可利用此特性来检查是否设置了变量的值。
newvar= 
echo ${newvar:?没有设置newvar的值} 
bash: newvar: 没有设置newvar的值 
newvar=a 
echo ${newvar:?没有设置newvar的值} 
a 


5、补充扩展:在上面这五种替换结构中string不一定是常值的,可用另外一个变量的值或是一种命令的输出。 
echo ${var:-`date`} 
日 3月 6 02:10:39 CST 2005 
echo ${var:-$(date)} 
日 3月 6 02:11:46 CST 2005 
a=test 
echo ${var:-$a} 
test 

四种模式匹配替换结构

# 去掉左边(在键盘上#在$的左边)
% 去掉右边(在键盘上%在$的右边)
#和%中的单一符号是最小匹配,两个相同符号是最大匹配
${var%pattern},${var%%pattern},${var#pattern},${var##pattern}

${var%pattern}:shell在var中寻找,判断是否以pattern模式结尾,如果是,就从命令行把var中内容去掉右边最短的(精简模式)匹配模式
${var%%pattern}:shell在var中寻找,判断是否以pattern模式结尾,如果是,就从命令行把var中内容去掉右边最长的(贪婪模式)匹配模式

${var#pattern}:shell在var中寻找,判断是否以pattern模式开始,如果是,就从命令行把var中内容去掉左边最短的(精简模式)匹配模式
${var##pattern}:shell在var中寻找,判断是否以pattern模式开始,如果是,就从命令行把var中内容去掉左边最长的(贪婪模式)匹配模式

结构中的pattern支持通配符,*表示零个或多个任意字符,?表示仅与一个任意字符匹配,[...]表示匹配中括号里面的字符,[!...]表示不匹配中括号里面的字符


举例:
#!/bin/bash
var=testcase
echo ${var%s*e}   #结果:testca (精简模式) 删除以s*e结尾
echo ${var%%s*e}  #结果:te     (贪婪模式) 删除以s*e结尾

echo ${var#?e}    #结果:stcase (精简模式) 删除开始到二个e
echo ${var##?e}   #结果:stcase (贪婪模式) 删除开始到二个e

echo ${var##*e}   #结果:为空全部匹配即全部删除
echo ${var##*s}   #结果:e      (贪婪模式) 删除开始到倒数第二个s

字符串提取和替换

${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

举例:
#!/bin/bash
var=helloword

echo ${var: 2}     #结果:lloword
echo ${var: -2}    #结果:hellowo
echo ${var:2:3}    #结果:llo
echo ${var/o/p}    #结果:hellpword   将var中第一个匹配的o替换为p
echo ${var//o/p}    #结果:hellpwprd  将var中所有匹配的o替换为p

分述如下:

1.Shell中变量的原形:${var}大家常见的变量形式都是$var,如 
 var=test 
 echo $var 
test
但当你要显示变量值加随意的字符(我这里用AA)时,就会出错,如下: 
 echo $varAA

这时应该用变量的原形:${var},即是加一个大括号来限定变量名称的范围,如下 
 echo ${var}AA 
testAA 

以这个特性,我们可以很方便地写一个批量改后缀名的程序,我把它命名为mymv,程序如下:

mymv.sh
#!/bin/bash
tail=$1 
for filename in `ls` 
do 
mv $filename ${filename}.$tail 
done
程序需要提供一个后缀名,如c,表示改为后缀为c的C程序文件,看下面的测试: 
ls 
a b c 
mymv c 
ls 
a.c b.c c.c 

一串的命令执行:()和{}都是对一串的命令进行执行,但有所区别:

()只是对一串命令重新开一个子shell进行执行
{}对一串命令在当前shell执行
()和{}都是把一串的命令放在括号里面,并且命令之间用;号隔开
()最后一个命令可以不用分号
{}最后一个命令要用分号
{}的第一个命令和左括号之间必须要有一个空格
()里的各命令不必和括号有空格
()和{}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令

#我们来看几个例子:
var=test 
(var=notest; echo $var)  【变量var值为notest,此时在子shell中有效】 
notest 
echo $var                【父shell中值仍为test】 
test 

 { var=notest; echo $var;}【注意左括号和var之间要有一个空格 】
notest 
echo $var                【父shell中的var变量的值变为了notest 】
notest 

{ var1=test1;var2=test2;echo $var1>a;echo $var2;} 【输出test1被重定向到文件a中】 
test2                                               【而test2输出则仍输出到标准输出中】 
cat a 
test1 

 { var1=test1;var2=test2;echo $var1;echo $var2;}>a 【括号内命令的标准输出全部被重定向到文件a中】
cat a 
test1 
test2

OSIX标准的扩展计算:$((exp))这种计算是符合C语言的运算符,也就是说只要符合C的运算符都可用在$((exp)),甚至是三目运算符。

注意:这种扩展计算是整数型的计算,不支持浮点型.若是逻辑判断,表达式exp为真则为1,假则为0。

echo $((3+2)) 
5 
echo $((3>2)) 
1 
echo $((25<3 ? 2:3)) 
3 
echo $var
echo $((var=2+3)) 
5 
echo $var 
5 
echo $((var++)) 
5 
echo $var 
6 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。