SHELL脚本编程进阶(一)
写在前面(最重要)
前言
分支与循环
分支条件选择if语句
单分支的if语句
if判断条件;then COMMANDS ... fi 多分支的if语句
if判断条件;then COMMANDS ... elif判断条件;then COMMANDS ... elif判断条件;then COMMANDS ... else COMMANDS ... fi
例子
#这是一个嵌套的if语句 a=3 if["$a"-gt0];then #then也可以写在下一行,这时就可以去掉分号 if["$a"-lt5];then echo"Thevalueof"a"liessomewherebetween0and5." fi fi #和下面的结果相同 if["$a"-gt0]&&["$a"-lt5] then echo"Thevalueof"a"liessomewherebetween0and5." fi
#读取用户输入的成绩 read-p"Pleaseinputyourscore"SCORE if["$SCORE"-lt60];then echo"不及格" elif["$SCORE"-ge60-a"$SCORE"-lt80];then echo"及格" elif["$SCORE"-ge80-a"$SCORE"-le100];then echo"优秀" fi 条件判断case语句
case"$variable"in "$condition1") command... ;; "$condition2") command... ;; esac 注意
case支持glob风格的通配符
示例
read-p"Pleaseinput[yes/no]"INPUT case$INPUTin [Yy]|[Yy][Ee][Ss]) echo"Yourwordisyes" ;; [Nn]|[Nn][Oo]) echo"Yourwordisno" ;; *) echo"Yourwordiswrong" ;; esac
#!/bin/bash#简易的通讯录数据库 #清屏 clear echo-e"ContactList ----------- ChooSEOneofthefollowingpersons: [E]vans,Roland [J]ones,Mildred [S]mith,Julie [Z]ane,Morris"echo read-p"PleasechooSEOnemenu[E|J|S|Z]"person case"$person"in #注意变量是被引用的。 "E"|"e") #同时接受大小写的输入。 echo-e" RolandEvans 4321FlashDr. Hardscrabble,CO80753 (303)734-9874 (303)734-9892fax revans@zzy.net Businesspartner&oldfriend" ;; #注意用双分号结束这一个选项。 "J"|"j") echo-e" MildredJones 249E.7thSt.,Apt.19 NewYork,NY10009 (212)533-2814 (212)533-9972fax milliej@loisaida.com x-girlfriend birthday:Feb.11" ;; *) #缺省设置。 #空输入(直接键入回车)也是执行这一部分。 echo echo"Notyetindatabase." ;; esac echo exit0
#!/bin/bash #使用命令替换生成"case"变量。 case$(arch)in#$(arch)返回设备架构。 #等价于'uname-m"。 i386) echo"80386-basedmachine" ;; i486) echo"80486-basedmachine" ;; i586) echo"Pentium-basedmachine" ;; i686) echo"Pentium2+-basedmachine" ;; X86_64) echo"X86_64-basedmachine" ;; *) echo"Othertypeofmachine" ;; esac exit0 select
selectvariable[inlist] do command... break done
#!/bin/bash PS3='Chooseyourfavoritevegetable:'#设置提示字串。 #否则默认为#?。 echo selectvegetablein"beans""carrots""potatoes""onions""rutabagas" do echo echo"Yourfavoriteveggieis$vegetable." echo"Yuck!" echo break#如果没有'break',整个代码会一直循环下去,直到按了Ctrl+C为止。 done exit
1)beans 2)carrots 3)potatoes 4)onions 5)rutabagas Chooseyourfavoritevegetable:1 Yourfavoriteveggieisbeans. Yuck!
#!/bin/bash PS3='Chooseyourfavoritevegetable:' echo choice_of(){ selectvegetable #[inlist]被省略,因此'select'将会使用传入函数的参数作为list。 do echo echo"Yourfavoriteveggieis$vegetable." echo"Yuck!" echo break done } choice_ofbeansricecarrortsradishesrutabagaspinach #$1$2$3$4$5$6 #传入了函数choice_of() exit0 循环
for 循环 for arg in [list]
forvarinitem1item2...itemN do command1 command2 .... ... commandN done
#直接给出整数列表 forvarin1234...100 do command1 command2 .... ... commandN done #或者直接生成整数列表 forvarin{1..100..2} do command1 command2 .... ... commandN done #或者直接生成整数列表 forvarin$(seq02100)##seq[start[step]]end do command1 command2 .... ... commandN done
#直接给出整数列表 forvarin$(ls*) do command1 command2 .... ... commandN done
forvarin*.sh do command1 command2 .... ... commandN done
fileNames="HELLO1HELLO2HELLO3HELLO4" forvarin$fileNames do command1 command2 .... ... commandN done
ArrayName=(/etc/*.conf) forvarin${ArrayName[@]} do command1 command2 .... ... commandN done
检查某些指定的文件是否存在 #!/bin/bash #fileinfo.sh FILES="/usr/sbin/accept /usr/sbin/pwck /usr/sbin/chroot /usr/bin/fakefile /sbin/badblocks /sbin/ypbind"#你可能会感兴趣的一系列文件。 #包含一个不存在的文件,/usr/bin/fakefile。 echo forfilein$FILESdo if[!-e"$file"] #检查文件是否存在。 then echo"$filedoesnotexist."; echo continue#继续判断下一个文件。 fi echo done exit0 while 循环
while[condition] do command1 ... commandN done
示例:简单的while循环 #!/bin/bash var0=0 LIMIT=10 while["$var0"-lt"$LIMIT"] do echo-n"$var0"#-n不会另起一行 var0=`expr$var0+1`#var0=$(($var0+1))效果相同。 #var0=$((var0+1))效果相同。 #let"var0+=1"效果相同。 done#还有许多其他的方法也可以达到相同的效果。 示例:多测试条件的while循环
#!/bin/bash var1=unset previous=$var1 whileecho"previous-varialbe=$previous" echo previous=$var1 #记录下$var1之前的值。 ["$var1"!=end] #在while循环中有4个条件,但只有最后的那个控制循环。 #最后一个条件的退出状态才会被记录。 do echo"Inputvariable#1(endtoexit)" readvar1 echo"variable#1=$var1" done exit0 示例:在 while 循环中结合 read 命令,我们就得到了一个非常易于使用的 while read 结构。它可以用来读取和解析文件 。 whilereadvalue#一次读入一个数据。 do echo"Thevalueis$value" done until
until[condition-is-true]docommands(s)...done 示例:读取用户输入,并输出到标准输出上,如果是end结束 #!/bin/bash END_CONDITION=end until["$var1"="$END_CONDITION"] #在循环顶部测试条件。 do echo"Inputvariable#1" echo"($END_CONDITIONtoexit)" readvar1 echo"variable#1=$var1" echo done 循环控制 break,continue,shiftbreak [N],continue [N]
#!/bin/bash #"continueN"命令可以影响其上N层循环。 forouterinIIIIIIIVV#外层循环 do echo; echo-n"Group$outer:" #-------------------------------------------------------------------- forinnerin12345678910#内层循环 do if[["$inner"-eq7&&"$outer"="III"]] then continue2#影响两层循环,包括“外层循环”。 #将其替换为普通的"continue",那么只会影响内层循环。 fi echo-n"$inner"#78910将不会出现在"GroupIII."中。 done #-------------------------------------------------------------------- done exit0 shift [N]
示例:批量添加用户,并能够根据输入的选项,进行不同的输出 #使用示例 #./user.sh--addMAGE,WANG,HELLO-v #./user.sh-h #!/bin/bash DEBUG=0 ADD=0 DEL=0 forIin`seq$#`;do case$1in -v|--verbose) DEBUG=1 #是否用来输出详情 shift #参数列表向左移动1个 ;; -h|--help) echo"Usage:`basename$0`--addUSER_LIST--delUSER_LIST-v|--verbose-h|--help" exit0 ;; --add) ADD=1 ADDUSERS=$2 shift2 ;; --del) DEL=1 DELUSERS=$2 shift2 ;; esac done if[$ADD-eq1];then forUSERin`echo$ADDUSERS|sed's@,@@g'`;do #将用户列表分割 ifid$USER&>/dev/null;then [$DEBUG-eq1]&&echo"$USERexists" elseuseradd$USER [$DEBUG-eq1]&&echo"Adduser$USERfinished." fi done fi if[$DEL-eq1];then forUSERin`echo$DELUSERS|sed's@,@@g'`;do ifid$USER&>/dev/null;thenuserdel-r$USER [$DEBUG-eq1]&&echo"Deleteuser$USERfinished" else [$DEBUG-eq1]&&echo"user$USERnotexists." fi done fi 特殊用法
for((EXPR1;EXPR2;EXPR3));do COMMAND .... COMMAND done #例如输出1-10 LIMIT=10 for((a=1;a<=LIMIT;a++))#双圆括号语法,不带$的LIMIT do echo-n"$a" done
until((EXPR));do COMMAND .... COMMAND done #例输出0-10 LIMIT=10 var=0 until((var>LIMIT)) do#^^^^^^没有方括号,没有$前缀。 echo-n"$var" ((var++)) done#012345678910
while((EXPR1))#双圆括号结构, do done #例如实现1-10的和 LIMIT=10 while((a<=LIMIT))#双圆括号结构, do#+并且没有使用"$"。 echo-n"$a" ((a+=1))#let"a+=1" #是的,就是这样。 #双圆括号结构允许像C语言一样自增一个变量。 done
#依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line whilereadline;do 循环体 done</PATH/FROM/SOMEFILE 在实际的使用过程中,可以实现多种循环的嵌套,以便实现复杂任务,应当具体情况具体分析。 如何在 for,while 和 until 之间做出选择?我们知道在C语言中,在已知循环次数的情况下更加倾向于使用 for 循环。但是在Bash中情况可能更加复杂一些。Bash中的 for 循环相比起其他语言来说,结构更加松散,使用更加灵活。因此使用你认为最简单的就好。 个人博客地址:http://www.pojun.tech/欢迎访问 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |