4.5 流程控制语句
和其他高级程序设计语言一样,Shell提 供了用来控制程序和执行流程的命令,包括条件分支和循环结构,用户可以用这些命令创建复 杂的程序。
与传统语言不同的是,Shell用于指定条件值的不是布尔运算式, 而是命令和字符串。
4.5.1 If
if [条件表达式] then 语句序列 fi # 如果你喜欢,也可以将 then 和 if 写在一行: if [条件表达式]; then 语句序列 fi # ------------------------------------------------------------------------- if [条件表达式]; then 语句序列1 else 语句序列2 fi # ------------------------------------------------------------------------- if [条件表达式1]; then 语句序列1 elif [条件表达式2]; then 语句序列2 ... else 语句序列n fi
4.5.2 case
case var in 表达式1) ... ;; 表达式2) ... ;; 表达式3) ... ;; *) # 用通配符*来处理无匹配的情况,相当于其他语言中的default ... esac
【例子】
[root@VM-24-17-centos shellstudy]# vim casetest.sh #!/bin/bash echo "*********************************" echo "please select your operation:" echo "press "C" to copy" echo "press "D" to delete" echo "press "B" to backup" echo "*********************************" read op case $op in C) echo "your selection is copy" ;; D) echo "your selection is delete" ;; B) echo "yourl selection 1s backup" ;; *) echo "invalide selection" esac [root@VM-24-17-centos shellstudy]# chmod u+x casetest.sh [root@VM-24-17-centos shellstudy]# ./casetest.sh ********************************* please select your operation: press C to copy press D to delete press B to backup ********************************* C your selection is copy
4.6 循环结构
在Shell程序中可以使用循环控制语句。
当循环次数已知或确定时,可以使用for循环语句来多次执行一条或一组命令,循环体由语句括号do和done来限定。
根据判断条件是否为真,使用while语句和until语句实现循环操作。
如果需要在未达到循环结束条件时强制跳出循环,通过break和continue实现。
4.6.1 for
- for语法1:
for 变量名 in 参数列表 do 命令列表 done
将"参数列表"中的元素依次赋给"变量名“,在每次赋值后执行"命令列表”,"参数列表"表示"变量名"的取值范围。
【例子】
[root@VM-24-17-centos shellstudy]# vim for.sh #!/bin/bash for day in sunday monday tuesday wndnesday thursday friday saturday do echo "this is : ${day}" done [root@VM-24-17-centos shellstudy]# chmod u+x for.sh [root@VM-24-17-centos shellstudy]# ./for.sh this is : sunday this is : monday this is : tuesday this is : wndnesday this is : thursday this is : friday this is : saturday
for语法2:
这种和我们平时学的高级语言中的for循环差不多。
for ((表达式1; 表达式2; 表达式3)) do 语句序列 done
表达式1: 赋值语句,循环结构的初始部分,为循环变量赋初值;
表达式2:条件语句,循环结构的循环条件;
表达式3:迭代语句,通常使用 ++ 或 – 运算符,循环结构的迭代部分,通常用来修改循环变量的值;
【例子】
[root@VM-24-17-centos shellstudy]# vim for2.sh #!/bin/bash for ((i=0; i <= 5; i++)) do echo "${i}" done for ((i=1,j=10; i <= 5; i++,j=j+5)) do echo "Number ${i}: ${j}" done [root@VM-24-17-centos shellstudy]# chmod u+x for2.sh [root@VM-24-17-centos shellstudy]# ./for2.sh 0 1 2 3 4 5 Number 1: 10 Number 2: 15 Number 3: 20 Number 4: 25 Number 5: 30
4.6.2 while
语法:
while [条件表达式] do 命令列表 done
循环执行“命令列表”中的命令,直至“条件表达式”的值为假。
4.6.3 until
语法:
until [条件表达式] do 命令列表 done
循环执行“命令列表”中的命令,直至“条件表达式”的值为真。
4.6.4 break 和 continue
break
:终止当前循环continue
:忽略本次循环continue之后的语句,进入下一轮循环。
4.7 函数
4.7.1 函数的定义
# 形式1: function 函数名 { 函数体 } # 形式2: 函数名(){ 函数体 }
注意:
- 第一种形式里,函数名和大括号之间要有空格;
[root@VM-24-17-centos shellstudy]# vim func1.sh #!/bin/bash function testSum{ let sum=3+4 # 注意,运算符两侧不要有空格 echo "3+4=${sum}" } testSum [root@VM-24-17-centos shellstudy]# chmod u+x func1.sh [root@VM-24-17-centos shellstudy]# ./func1.sh ./func1.sh: line 3: syntax error near unexpected to ken `let' ./func1.sh: line 3: ` let sum=3+4 '
可以看到并没有像想象中一样运行成功,而是报错了,意思有语法错误,在第三行let的地方(4.3 数值计算 有说let的使用),可是我们发现并没有错误, 那么我们就要看一下它周边的代码有没有问题,问题就出在空格:
function testSum{ # 少了个空格 function testSum {
4.7.2 函数调用
函数名 #注意不需要括号 # 如果需要参数 函数名 参数1 参数2 ...
注意:
- 调用函数时传递的参数,在函数体中可以通过位置变量
$1 $2 ...
使用;
[root@VM-24-17-centos shellstudy]# vim func1.sh #!/bin/bash testSum(){ if [ $# -ne 2 ];then echo "not enough parameters!" echo "example ./func1.sh 1 2" exit 0 # 正常退出 fi let sum=$1+$2 echo "$1+$2=${sum}" } testSum $1 $2 # 注意,这里不要忘记把参数传递给函数 [root@VM-24-17-centos shellstudy]# ./func1.sh not enough parameters! example ./func1.sh 1 2 [root@VM-24-17-centos shellstudy]# ./func1.sh 1 2 1+2=3
4.7.3 返回值
[root@VM-24-17-centos shellstudy]# vim func1.sh #!/bin/bash testSum(){ if [ $# -ne 2 ];then echo "not enough parameters!" echo "example ./func1.sh 1 2" exit 0 # 退出 fi let sum=$1+$2 return ${sum} } testSum $1 $2
如何访问到返回值:
- 通过
$?
(3.3 预定义变量 有说)访问:
[root@VM-24-17-centos shellstudy]# vim func1.sh ... echo "$?" [root@VM-24-17-centos shellstudy]# ./func1.sh 1 2 3
- 注意,如果通过这种方式,在调用函数和访问返回值之间不要出现其他语句
4.7.4 递归
实例:阶乘
#!/bin/bash function fac { i=$1 if [ ${i} -eq 1 ];then echo 1 else let j=${i}-1 k=`fac ${j}` echo `expr ${i} \* ${k}` fi } while true do read -p "please input an interger('q' to quit): " num if [ ${num} = 'q' ];then break fi rtn=`fac ${num}` echo "answer is ${rtn}" done
注意:
rtn=`fac ${num}`
- 并不是我们以为的那种获取函数返回值,echo xxx是输出到标准输出,
fac
函数通过echo将结果输出到标准输出,然后最终赋值给rtn的,``是返回命令的执行结果;
4.8 数组
- 定义数组
declear -a 变量名 #或者 变量名=(val1 val2 val3 ...) # 或者 变量名=([下标1]=val1 [下标2]=val2 ...) #这个并不影响你获取的数组长度,不会因为你arr1=([10]=1),数组就长10,数组长度是你数组的元素个数。
- 初始化
数组名[index]=值
- 访问数组元素:
${数组名[${下标}]}
- 访问数组长度(数组元素个数)
${#数组名[*]}
【例子1】
[root@VM-24-17-centos shellstudy]# vim arr.sh #!/bin/bash arr1=(1 2 3 4) echo "arr1=[${arr1[*]}]" echo "len(arr1)=${#arr1[*]}" for ((i=0; i < ${#arr1[*]}; i++)) do echo -n -e "${arr1[${i}]}\t" done echo "" [root@VM-24-17-centos shellstudy]# chmod u+x arr.sh [root@VM-24-17-centos shellstudy]# ./arr.sh arr1=[1 2 3 4] len(arr1)=4 1 2 3 4
【例子2】
[root@VM-24-17-centos shellstudy]# vim arr2.sh #!/bin/bash arr1=([3]=1 [4]=2 [5]=3 [6]=4) echo "arr1=[${arr1[*]}]" echo "len(arr1)=${#arr1[*]}" echo "方法1" for ((i=0; i < ${#arr1[*]}; i++)) do echo -n -e "${arr1[${i}]}\t" done echo "" echo "方法2" for var in ${arr1[*]} do echo -n -e "${var}\t" done echo "" [root@VM-24-17-centos shellstudy]# chmod u+x arr2.sh [root@VM-24-17-centos shellstudy]# ./arr2.sh arr1=[1 2 3 4] len(arr1)=4 方法1 1 方法2 1 2 3 4
注意:
下标从0开始
数组成员不必一定要连贯或连续的;
数组的一部分成员允许不被初始化;
数组中空缺元素是允许的;
5. 补充
查看登录用户信息:
who am i :当前登录用户,信息较为全面
whoami: 只显示登录用户名
who:较为全面的所有登录用户信息
w:更全面的所有登录用户信息