1. 运算和赋值
1.1. 算术运算
bash中的算术运算:
help let
+, -, *, /, %取模(取余), **(乘方),乘法符号有些场景中需要转义实现算术运算:
(1)let var=算术表达式,由于用了let就知道是为了计算,因此后面的算术表达式如果使用变量的时候 ,就无须使用变量引用符号$,直接使用变量名即可。
(2)var=$[算术表达式]
(3)var=$((算术表达式))
(4)var=$(expr arg1 arg2 arg3 ...)expr本身是一个命令,就是用于计算的,后面的参数注意每一个都要用空格符分开用来区分;- 参数只能是数字,可以用
$var的方式把变量内的数字当做参数 - 注意这里引用变量内的数值的时候,就必须加上参数扩展符号
$,不能像前面几个命令那样不用加这个符号直接写变量名也可进行计算,这里必须加上 - expr后面的计算符乘号
*之前要加\需要转义,不然会当做通配符
(5)
declare –i var = 数值, 比如declare -i N ; N=x+y便可以直接运算,x,y前也不需要再加$等其他符号;或者说赋值和计算同时进行也可以。- 如果不加-i的话,必须用前面的算术扩展符号才能计算;例如
N=$((x+y)) - 注意:如果将已经定义了数字型的变量赋值字符串,则它的内容会被设定为数值0 ,所以不能把定义了数字型的变量再当做普通变量来用。
[06:26:49 root]# declare -i NN [06:27:45 root]# x=1 [06:27:49 root]# y=2 [06:27:50 root]# NN=x+y [06:28:02 root]# echo $NN 3 [06:28:05 root]# NN=EFESAF [06:28:50 root]# echo $NN 0(6)
echo '算术表达式' | bc(这里的算术表达式指的是数值,不能直接用变量名,如果变量的内容是数值,则也需要用引用符号$把它引用之后再用管道输送到bc中,原因就是bc中只能接收数值,不能接受变量名和字符)注意点:上面的算术表达式里面的数值变量(中括号里,双小括号里和let后面的)已经不再需要前面加上$符号了,因为算术表达式符号(中括号,双小括号,let)已经指定它后面的是数值,如果后面跟的不是数值(也就是字符)则就可以判断出这个字符是变量(如果这个变量没有被赋值或者是字符串变量,则在算术表达式中会被看做是0),但是加上也不会错
18:07[root@centos7 /data]# W=$[X*Y] 18:08[root@centos7 /data]# echo $W 12 18:08[root@centos7 /data]# W=$[$X-$Y] 18:09[root@centos7 /data]# echo $W -1bash有内建的随机数生成器变量:
$RANDOM(0-32767)示例:生成 0 – 49 之间随机数echo $[RANDOM%50]
例子:随机打印彩色字符$[RANDOM%7+31] 或者 $[$RANDOM%7+31] 或者 CNUM=\$[RANDOM%7+31]echo -e "\033[$[RANDOM%7+31]mCOLOR\033[0m" 或者 eval echo -e \\\\e[${CNUM}mCOLOR\\\\033[0m 或者 eval echo -e ""\\\\e[${CNUM}mCOLOR\\\\033[0m"" 或者 eval echo -e "\\\e[${CNUM}mCOLOR\\\033[0m" 或者 eval echo -e "\\\\e[${CNUM}mCOLOR\\\\033[0m" 或者 ... 最多添加几个\ 是相当于 echo -e \\\\ 不加双引号,测试如下 [07:27:03 root@localhost ~]# echo -e \\ \ [07:27:08 root@localhost ~]# echo -e \\\ > ^C [07:27:12 root@localhost ~]# echo -e \\\\ \ [07:27:14 root@localhost ~]# echo -e \\\\\ > ^C [07:27:17 root@localhost ~]# echo -e \\\\\\ \\ [07:27:19 root@localhost ~]# echo -e \\\\\\\\ \\ [07:27:20 root@localhost ~]# echo -e \\\\\\\\\\ \\\ [07:27:22 root@localhost ~]# echo -e \\\\\\\\\\\\ \\\ [07:27:24 root@localhost ~]# echo -e \\\\\\\\\\\\\\ \\\\
1.2. 赋值
- 增强型赋值:
+=, -=, *=, /=, %= let varOPERvalue
例如:let count+=3
自加3后自赋值- 自增,自减:
let var+=1
let var++
let ++var
let var-=1
let var-- :先赋值再计算
let --var : 先计算再赋值
- 比如 let j=i++ 和let j=++i ,结果就不同。
1.3. 逻辑运算
- true, false
- 1, 0
- 但注意在bash shell中 ,$?则分别为0和1,和计算机中和C语言中相反
- 例如:# true # echo $? 0 # false # echo $? 1
- 逻辑与 &&1 与 1 = 1 1 与 0 = 0 0 与 1 = 0 0 与 0 = 0
- 逻辑或 ||1 或 1 = 1 1 或 0 = 1 0 或 1 = 1 0 或 0 = 0
- 逻辑非:!! 1 = 0 ! true ! 0 = 1 ! false
1.4. 额外知识点:列表命令 &&和||
- 它属于bash里面的Lists of Commands部分,另外两个符号是
; 和 &(后台),具体查看man bash) - 短路与
&&:cmd1 && cmd2- 注:它先判断cmd1,根据它的结果真假,再判断cmd2是否需要执行;最后它整体也会输出一个判断值,下同。
- 第一个为0(假),则cmd2不进行计算,其结果必定为0(假);此时$?不为0;
- 第一个为1(真),第二个必须要参与运算
- 最终结果就是按照上面的规则,最后面(最右边)执行的命令的逻辑结果的值;
- 短路或
||- 第一个为1(真),结果必定为1(真);此时后面的命令不再执行;同时
$?为0(真); - 第一个为0(假),第二个必须要参与运算
- 同样的最终结果就是按照上面的规则,最后面(最右边)执行的命令的逻辑结果的值;
- 第一个为1(真),结果必定为1(真);此时后面的命令不再执行;同时
- 注意: 可以 ###### && ###### || ###### ,能够有判断效果
- 在某种情况下也可以 ##### || ##### && ##### ,这样的时候需要仔细判断
- 注意,想要 ##### 作为一个整体,不能用小括号,它开了一个子进程,要用花括号。
1.5. (比特)位元运算
位元与 : &
位元或 : |
位元非 : ~
位元异或:^
位元移位:数值或变量>>移位的位数(向右) , 数值或变量<<移位的位数(向左)
- 异或的两个值,相同为假,不同为真
- 附加:根据异或的特性,两个值异或出来的结果,再与其中一个值异或,得到的是另外一个值,可以将两个数的值对调,例子:
18:10[root@centos7 /data]# x=10;y=8;x=$[x^y];let y=x^y;x=$((x^y));echo $x $y
8 10
18:31[root@centos7 /data]# x=10;y=8;temp=$x;x=$y;y=$temp;echo $x $y
8 10
2. 条件测试
- 判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程
- 评估布尔声明,以便用在条件性执行中
若真,则返回0
若假,则返回1
- 测试命令:
test EXPRESSION : test $name1 = $name2
[ PATTREN ] :和上面相同,**精确匹配**,不支持正则表达式和通配符
[[ EXPRESSION ]] :支持扩展正则表达式和通配符,**可以模糊匹配**
- 注意:EXPRESSION和PATTERN前后必须有空白字符(不带空格变成了变量赋值),还要注意它与前面的算术运算的区别:算术运算的中括号前面有$,括号里面的表达式不需要与边上有空格。
- 双中括号中
=~右边的正则表达式不能加双引号,否则会变成字符匹配(通配符),但是前面的变量引用要加上双引号,为了避免变量是空的导致我们不想要的结果,同样单中括号最好也是加上双引号,但是不能加单引号,不然就无法变量扩展了 - 双中括号还可以用 (EXPRESSION) ; !EXPRESSION ; $$ ;|| 的用法,但是不支持后面的单中括号的-a -o这种用法来代表$$ ||.
- 更多区别可查看他人总结的各种括号的区别以及内部帮助help test help [ man bash , /\[\[ man bash , /test man bash , /patterning match man bash , /conditional expression man bash , /arithmetic evaluation
2.1. 数值大小测试
-v VARNAME :判断变量VARNAME是否被set了
注意这里是 VAR 不是 string,直接写变量名不用加$符号;
而下面的 -n 和 -z 后面跟的是 string,因此如果想用它俩查看变量内是否为空则需要变量前加$符号(同时注意别忘了把变量用双引号括起来)
变量VAR是否设置 :这个就是用来判断变量是否存在,比如var="", 虽然它是空值,但是它仍然赋值设置过已经存在了,
[ -v var ] ,echo $? =0结果为真注意这个里面判断的时候直接跟变量名,不需要加$符号
除了这个-v判断条件的情况外,只有算术运算中(也就是双小括号中)变量可以不用$符号,其他任何时候都需要加$符号,注意单双中括号中都是条件判断表达式,并不是算术运算
注意它和-n的区别,-n如果变量不存在或者变量为空都返回1 false,而-v只关心变量存不存在(是否被set),不管里面的值是什么,变量只要存在就为0 true
数值测试:
-gt 是否大于
-ge 是否大于等于
-eq 是否等于
-ne 是否不等于
-lt 是否小于
-le 是否小于等于
- 注意:当用数值比较的时候,前面的变量最好要提前先做一次判断,判断它1.是否非空2.且是否是一个数,然后再进行比较判断。这样可以避免报错以及数值变量两边不需要加双引号。
- 同样其他的任何变量,比如字符串变量和数组变量等等,都可以提前先做一次这样的操作。
- 具体在脚本中是用自己所写的判断函数来进行测试的,同时判断的时候也可以用双中括号,这样可以利用
> <等符号
2.2. 字符串测试:
= 是否等于,主要用于test(实际上用在[[ ]]内部也没关系,但一般双中括号里面用== )仍旧是通配符匹配
> ascii码是否大于ascii码,字符串从左往右一个一个比较(test或单中括号中)(注意在双中括号中,则是按照current locale来进行比较的,也就是比较sort命令的前后顺序)
< 是否小于
- 注意:上面两个比较在单中括号
[]里面都需要转义,不然看做重定向,但是在[[]]里面不需要转义可以直接用,但也因此导致了词首词尾锚定不能用了,往下看有例子会解释。
13:58[root@centos7 /data]# AAA="abc$"
13:58[root@centos7 /data]# BBB="abc#"
13:58[root@centos7 /data]# [ $AAA \> $BBB ]
13:58[root@centos7 /data]# echo $?
0
13:58[root@centos7 /data]# BBB="abc%"
13:58[root@centos7 /data]# [ $AAA \< $BBB ]
13:58[root@centos7 /data]# echo $?
0
!= 是否不等于
== 是否等于
==(其实=也是的) 或者!= ,后面匹配的是partern通配符(pathname扩展),而不是正则表达式。
== 用于双中括号,=用于单中括号;
== 双中括号后面匹配通配符, 单中括号=后面不能匹配通配符。
=~ 左侧字符串是否能够被右侧的正则表达式ReExPression所匹配,(注意这个符号虽然含有等号,但是它的逻辑和grep是类似的,只要能匹配到就行,而不是说要完全相同)
- 注意
=~符号,它的匹配只要能匹配到即可,包含什么东西,带什么东西都行,并非要完全匹配,比如匹配以.sh结尾的,则只需[[ "$var" =~ \.sh$ ]],而并不需要非得写成[[ "$var" =~ .*\.sh$ ]] - 注意: 在
[[]]中;匹配的是扩展的正则表达式 例如:str=abc ; [[ $str =~ ^a ]]
-z "STRING“ 字符串的长度是否为0,长度是0为真,不是0为假 :
[-z "$str"] ([-z $str]也可使用,但最好不要这样写)
-n "STRING“ 字符串的长度是否不为0,长度不是0为真,长度是0为假 :
[ $awdfc ] ,echo $?=1 (awdfc没赋值和定义)
注意:[] 中间省略了-n,只要里面有内容,字符串或者数字等等不为空,他的结果就为真,
$?就为0,反之随便跟一个没定义赋值的变量,因为里面是空的,所以它的结果就为假,$?为1(别忘了加双引号把变量给括起来).例如:
[ -n "" ] ,echo $?=1- 但是注意,如果
[ -n $var ],如果var没有定义,它的结果也显示为真的(正常情况下应该为假,比如不加-n的时候[ $var ]就是假的),因为var两边没有加上"$var", 必须加上双引号并且var没有定义或者为空,结果才为假的. 所以不加双引号时这种用法不正确,必须加上双引号 - 同时注意这里面不写
-n的时候双引号加上不加上都可以没有影响,除非变量的内容是判断空格,此时就算没有-n,这里不加上双引号的话结果为假,也是不正确的。 - 由此可见,不论怎样,在单双中括号的变量引用
$var两边都要加上双括号才能保证结果完全正确
- 但是注意,如果
还有个技巧
[ "x$var" = "x"]也可以判断var里面是否为空 ,为空结果为真。注意空格也算是字符,只有任何字符没有才是空
注意:用于字符串比较时的用到的操作和变量都应该使用双引号括起来,(单引号会强引用,注意场合使用它),这样是为了避免空变量或者空字符在判断中因其错误,比如下面例子:
如果两个变量都是空的
[ $wadc = $wvaf ] ;echo &?=0
[ "$wadc" = "$wvaf" ] ;echo &?=0
但是如果一个变量是空的,一个变量是非空的则会报错
[ $wadc = $wvaf ] ;
-bash: [: wad: unary operator expected
echo &?=2
因此字符串比较都要加上引号
注意:如果把
数字当做是普通的字符串来进行比较,也可以用[ "##" = "##" ]这类字符串比较的符号而不是用数字比较的符号(-gt等等), 但此时需要注意两边都要加上引号变为字符串, 但加上引号之后就不能再用 -eq等命令了。判断一个变量是否为数字:
[[ "$n" =~ ^[0-9]+$ ]]- 注意用词首词尾不能判断,原因是它把单个
<或>当做是判断字符串的sort顺序,因此当输入\<或\>的时候看做转义了<或>,也就把它当做了一个普通符号来看待, - 同时
\b也是相当于转义了一下b,相当于还是输出一个b普通字符;(其他的任何字符也都是类似一样的,用\符号转义了一下和没有转义的时候,用于正则表达式匹配意义相同) - 因此在
[[]]中,无法使用词首词尾锚定的扩展正则表达式 - 看下面的例子:
- 注意用词首词尾不能判断,原因是它把单个
12:44[root@centos7 /data]# num="<123>"
12:44[root@centos7 /data]# [[ "$num" =~ \<[0-9]+\> ]]
12:44[root@centos7 /data]# echo $?
0
12:46[root@centos7 /data]# num=/123/
12:46[root@centos7 /data]# [[ "$num" =~ \<[0-9]+\> ]]
12:46[root@centos7 /data]# echo $?
1
12:48[root@centos7 /data]# num="123>"
12:48[root@centos7 /data]# [[ "$num" =~ \<[0-9]+\> ]]
12:48[root@centos7 /data]# echo $?
1
12:52[root@centos7 /data]# num="\<123\>"
12:52[root@centos7 /data]# [[ "$num" =~ \\\<[0-9]+\\\> ]]
12:52[root@centos7 /data]# echo $?
0
--------------------------------
反斜杠\b也用不了:
13:01[root@centos7 /data]# [[ `echo 123` =~ \b[0-9]+\b ]]
13:03[root@centos7 /data]# echo $?
1
13:03[root@centos7 /data]# [[ `echo b123` =~ \b[0-9]+\b ]]
13:03[root@centos7 /data]# echo $?
1
13:03[root@centos7 /data]# [[ `echo b123b` =~ \b[0-9]+\b ]]
13:03[root@centos7 /data]# echo $?
0
13:03[root@centos7 /data]# [[ `echo \b123\b` =~ \b[0-9]+\b ]]
13:04[root@centos7 /data]# echo $?
0
13:16[root@centos7 /data]# [[ `echo b123rb` =~ \b[0-9]+\b ]]
13:17[root@centos7 /data]# echo $?
1
13:17[root@centos7 /data]# [[ `echo b123\b` =~ \b[0-9]+\b ]]
13:17[root@centos7 /data]# echo $?
0
- 但是用grep命令可以,看下面的例子:
11:58[root@centos7 /data/scriptest]# num=123; [[ $num =~ ^[0-9]+$ ]]
11:59[root@centos7 /data/scriptest]# echo $?
0
11:59[root@centos7 /data/scriptest]# num=123; [[ $num =~ \<[0-9]+\> ]]
11:59[root@centos7 /data/scriptest]# echo $?
1
但是用grep命令可以:
12:19[root@centos7 /data]# echo /123/ |egrep "\<[0-9]+\>"
/123/
12:19[root@centos7 /data]# echo 123/ |egrep "\<[0-9]+\>"
123/
12:19[root@centos7 /data]# echo a123b | egrep "\<[0-9]+\>"
12:20[root@centos7 /data]# echo 123b | egrep "\<[0-9]+\>"
12:20[root@centos7 /data]# num=123
12:20[root@centos7 /data]# [[ "$num" =~ "\<[0-9]+\>" ]]
12:20[root@centos7 /data]# echo $?
1
12:21[root@centos7 /data]# echo $num
123
- 判断一个变量内容是否是以sh后缀:
[[ "$variable" =~ .*\.sh$ ]] - 注意后面的正则表达式不能再加双引号了,不然会把双引号里面的看作是
普通的字符串,就不再是正则表达式了,当然同样的,单引号或者反向双引号了也不能加。 - 同理,在
[[ "$var" == pattern ]]中的pattern通配符表达中,pattern两边也不能加双引号,不然也会被看做是普通的字符串。
例子:
12:56[root@centos7 /data]# [[ `echo "123"` =~ ".*" ]]
12:57[root@centos7 /data]# echo $?
1
12:57[root@centos7 /data]# [[ `echo ".*"` =~ ".*" ]]
12:59[root@centos7 /data]# echo $?
0
12:59[root@centos7 /data]# [[ `echo "".*""` =~ ".*" ]]
12:59[root@centos7 /data]# echo $?
1
12:59[root@centos7 /data]# [[ `echo "".*""` =~ "".*"" ]]
13:00[root@centos7 /data]# echo $?
0
- 但是前面的最好用上双引号,虽然不用也不会报错,但结果可能会出问题。还有,这种匹配都是匹配了字符,因此前面即使是数字的变量也要加上双引号。
num=123
12:26[root@centos7 /data]# [[ "$num" =~ "^[0-9]+$" ]]
12:26[root@centos7 /data]# echo $?
1
12:26[root@centos7 /data]# [[ "$num" =~ ^[0-9]+$ ]]
12:26[root@centos7 /data]# echo $?
0
同时还需要注意,不论怎样都无法用次首词尾来判断:
12:28[root@centos7 /data]# num=/123/
12:28[root@centos7 /data]# [[ "$num" =~ \<[0-9]+\> ]]
12:28[root@centos7 /data]# echo $?
1
但是grep中可以,但注意grep后面判断部分是最好加引号,否则无法将反斜杠\,以及<>重定向符号转义来来进行判断,因为会把它看作是新的一行来输入:
12:29[root@centos7 /data]# echo $num | egrep \<[0-9]+\>
12:31[root@centos7 /data]# echo $num | egrep "\<[0-9]+\>"
/123/
12:31[root@centos7 /data]# echo $num | egrep [0-9]+
/123/
但可以转义它,不过太过于复杂,所以还是加上引号比较好:
12:36[root@centos7 /data]# echo $num | egrep \\\<[0-9]+\\\>
/123/
- 短路或后面的语句如果是两条命令想要同时执行的,并且不开启子进程,必须得使用花括号括起来,并且它与每条命令之间要有空格分开,每条命令后面也要加上分号
3. Bash的文件测试
3.1. 存在性测试
-a FILE:同-e
-e FILE: 文件存在性测试,存在为真,否则为假
3.2. 存在性及类别测试
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件
- 注意:用-d判断是否是文件夹的时候,如果一个软链接指向一个文件夹,它也会把这个软连接当做一个文件夹返回正确的结果,因此,判断是否是文件夹之前,应先用-h或者-L判断是否是软链接
- 因此我们知道判断软连接的时候都是判断它指向的目标的文件的类型,应该需要提前判断是否为软链接再判断其它的。
- 或者两个条件同时判断:[ ! -h "file" ] && [ -d "file"] 或者 [ ! -h "file" -a -d "file"]
- 用双中括号的话则是[[ ! -h "file" ]] && [[ -d "file" ]] 或者 [[ ! -h "file" && -d "file" ]]
3.3. 文件权限测试:
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
- 注意:它是针对当前用户而言的真实权限,并不是完全按照ll列表中显示的来判断的。就比如root账号什么权限都有。
3.4. 文件特殊权限测试:
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限
3.5. 文件大小测试:
-s FILE: 是否存在且非空
3.6. 文件是否打开:
-t fd: fd 文件描述符是否在某终端已经打开
-N FILE:文件自从上一次被读取之后是否被修改过
-O FILE:当前有效用户是否为文件属主
-G FILE:当前有效用户是否为文件属组
3.7. 双目测试:
FILE1 -ef FILE2: FILE1是否是FILE2的硬链接
FILE1 -nt FILE2: FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2: FILE1是否旧于FILE2
4. Bash的组合测试条件
4.1. 第一种方式(条件判断):
[ EXPRESSION1 -a EXPRESSION2 ] 并且
[ EXPRESSION1 -o EXPRESSION2 ] 或者
[ ! EXPRESSION ]
[[ EXPRESSION1 && EXPRESSION2 ]] 并且
[[ EXPRESSION1 || EXPRESSION2 ]] 或者
[[ ! EXPRESSION ]]
- 注意:必须使用测试命令进行,
[[ ]]不支持-a -o,只支持符号的&& || ! - 但是
-a代表文件存在的表达式则在[[]]中可以使用
4.2. 第二种方式(命令列表):
COMMAND1 && COMMAND2 并且,短路与,代表条件性的AND THEN
COMMAND1 || COMMAND2 或者,短路或,代表条件性的OR ELSE
如:命令列表同时配合使用条件判断:
[ -f “$FILE” ] && [[ “$FILE”=~ .*\.sh$ ]]举例:
判断有没有用户:
grep -q no\_such\_user /etc/passwd || echo 'No such user
No such user
判断一个IP是否连通:
ping -c1 -W2 station1 &> /dev/null && echo "station1 is up" || (echo 'station1 is unreachable'; exit 1)
station1 is up
- 注意:这里小括号开启了子进程shell,利用
exit 1命令输退出子shell并让返回值为1;类似函数中的return 1,命令不是自己想要的结果的时候输出非0值这种写法,是一种标准格式和技巧。
13:31[root@centos7 /data/scriptest]# ( hostname ; exit 101 )
centos7.6test
15:09[root@centos7 /data/scriptest]# echo $?
101
- 可以用小括号临时创建不同文件权限的文件等操作
(umask 066 ;touch f1)
4.2.1. 附加:禁止普通用户登录可以创建一个普通文件/etc/nologin即可,删除它便可以解除。对root登陆没有影响。
5. read命令接收输入—{read,$REPLY,stty}
- 使用read来把输入值分配给一个或多个shell变量
- read 从标准输入中读取值,给每个单词分配一个变量
- 所有剩余单词都被分配给最后一个变量-p "string" :指定要显示的提示wall -s :静默输入,一般用于密码 - 例如 read -s password ,然后输入的密码不会在屏幕上显示 - 附加知识点:ctrl+s ,ctrl+q 或者 stty -echo ,stty echo;分别可以让标准输入和输出的内容在屏幕上不显示以及重新显示 -n N :指定输入的字符长度N:只要达到这个长度,命令就退出了 -d ‘字符’ :输入结束符,只要输入这个字符,read命令也就退出了 -t N :TIMEOUT为N秒
- 所有剩余单词都被分配给最后一个变量
例子: read -p “Enter a filename: “ FILE
5.1. 注意点:
- 如果不指定要接收的变量名,则默认赋值输入给
REPLY这个变量。 - read后面直接跟变量名,不需要加$
- read命令赋值参数如果用管道传给它的话,并不是说不可以,只不过由于管道命令会开批一个子shell,会让赋的值无法在当前shell中使用,例子在下面
- 如果read后面只写了n个name变量,但却输入了N个值(用空格隔开的),N>n, 前n-1个变量正常赋值,第n个变量会把剩下的字符包括空格全部赋值进去。
- 同理如果有M个变量,但是输入了m个值(用空格隔开),M>m,则前面的m个变量正常赋值,后面的变量为空。
15:09[root@centos7 /data/scriptest]# echo a b c | read x y z
15:29[root@centos7 /data/scriptest]# echo $x $y $z
15:34[root@centos7 /data/scriptest]# echo a b c | (read x y z;echo $x $y $z;)
a b c
15:30[root@centos7 /data/scriptest]# echo a b c | { read x y z;echo $x $y $z; }
a b c
- 注意例子中小括号中括号都可以,分别是小括号代表一个子进程中的命令, 以及中括号看作是管道自己开启的子进程中的整体命令,略有不同。需要注意中括号两边必须要有空格且所有命令后面加分号,小括号不需要。
6. 条件判断语句—{if,case}
6.1. 条件选择语句if
- 选择执行:
- 注意:if语句可嵌套
- 单分支
if 判断条件;then
条件为真的分支代码;
fi
- 双分支
if 判断条件; then
条件为真的分支代码;
else
条件为假的分支代码;
fi
- 多分支
if 判断条件1; then
条件1为真的分支代码;
elif 判断条件2; then
条件2为真的分支代码;
elif 判断条件3; then
条件3为真的分支代码;
else
以上条件都为假的分支代码;
fi
- 注意:逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
6.2. 条件判断case
case 变量引用(word) in
PAT1)
分支1
;;
PAT2)
分支2
;;
PAT..)
分支...
;;
*)
默认分支
;;
esac
6.2.1. case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
a|b: a或b
留言