【Linux基础】shell控制结构

时间:2021-12-06 05:49:06
shell程序设计语言的基础是对条件进行测试判断,根据不同的测试结果采取相应的程序处理。因此,下面我们将会先来分析在shell脚本程序中可以使用的判断条件,然后再来学习使用这些条件的控制结构。
1.4.3.2.1 判断条件
/************************************************/
1 条件测试
条件测试有二种常用形式:
第一种是用test命令与系统运算符一起使用,如上所示(例子说明)。
第二种是用一对方括号与系统运算符一起使用。这两种形式是完全等价的。例如,测试位置参数$1是否是已存在的普通文件,可写为test -f "$1"。也可写成[ -f "$1" ]。利用一对方括号表示条件测试时,在左方括号“[”之后、右方括号“]”之前各应有一个空格。(下面举例说明)
#!/bin/bash
if test -f "$1"
then echo "$1 is an ordinary file . "
else echo "$1 is not an ordinary file . "
fi
运行脚本程序得结果与上面完全一样。
/**********************************/
shell程序设计中被广泛使用的判断条件主要是布尔判断命令[与test,在大多数系统中,两者没有太大的区别,都使得程序设计语法看起来更加简单与明了,只是在形式上为了增强可读性,[命令会使用符号]来结尾。
下面分别为两者的语法结构:
test测试条件
测试条件
Test/[ 命令可以使用的条件类型可以归为以下三类:
字符串比较:
算术比较:
与文件有关的条件测试:
字符串比较 结果
String1 = string2 如果两个字符相同则结果为真
String1 != string2 如果两个字符不相同则结果为真
-n String 如果字符串不为空则为真
-z string 如果字符串为空(一个空串)则结果为真
算术比较 结果
Expression1 -eq expression2 如果两个表达式相等则结果为真
Expression1 -ne expression2 如果两个表达式不同则结果为真
Expression1 -g t expression2 如果expression1 大于expression2则结果为真
Expression1 -ge expression2 如果expression1 大于或等于expression2则结果为真
Expression1 - l t expression2 如果expression1 小于expression2则结果为真
Expression1 - le expression2 如果expression1 小于或等于expression2则结果为真
!Expression1 如果表达式为假则结果为真,反之亦然
文件条件比较 结果
-d file 如果文件是一个目录则结果为真
-e file 如果文件存在则结果为真。要注意的是历史上-e选项不可移植,所以通常使用的是-f选项
-f file 如果文件是一个普通文件则结果为真
-g file 如果文件的SGID位被设置则结果为真
-r file 如果文件可读则结果为真
-s file 如果文件的长度不为0则结果为真
-u file 如果文件的SUID位被设置则结果为真
-w file 如果文件可写则结果为真
-x file 如果文件可执行则结果为真
例子:检查环境变量PATH是否为空
test –z $PATH
[ -z $PATH ]
使用[]时要特别注意,在每个组件之间均要用空格键分隔,否则将会提示出错。
在实际shell程序设计中,使用单一判断条件的情况很少,其往往与&&、||等组成复合判断条件来使用。
语法结构:
判断条件1 && 判断条件2
判断条件3 || 判断条件4
语法分析:
判断条件1为真时才会执行判断条件2,否则忽略判断条件2
判断条件3为假时才会执行判断条件4,否则忽略判断条件4
实验5.3.2.1:设计出满足下面条件的shell程序
1、当执行一个程序的时候,这个程序会让用户选择y或n
2、如果用户输入y,就显示“OK,continue”
3、如果用户输入n,就显示“Oh,interrupt”
4、如果是其它字符,就显示“Please enter y or n”
[/home]# vi sh_1.sh
#!/bin/bash
echo -e "Are you sure?(y/n):\c"
read yn
[ $yn == "y" ] && echo "OK,continue" && exit 0
[ $yn == "n" ] && echo "Oh,interrupt" && exit 0
echo -e "Please enter y or n"
[/home]# ./sh_1.sh
Are you sure?(y/n):y
OK,continue
2.4.3.2.2 条件判断结构
1、if语句
if语句用于条件控制结构中
语法格式1
fi [条件判断表达式 ]; then
当条件表达式成立时,可以执行的命令
if
实验5.3.2.2:修改实验5.3.2.1以下
[/home]# vi sh_2.sh
#!/bin/bash
echo -e "Are you sure?(y/n):\c"
read yn
if [ $yn == "y" ] ;then
echo "OK,continue"
exit 0
fi
if [ $yn == "n" ]
echo "Oh,interrupt"
exit 0
fi
echo -e "Please enter y or n"
[/home]# ./sh_1.sh
Are you sure?(y/n):y
OK,continue
语法格式2
if [条件判断表达式 ];then
当条件表达式成立时,可以执行的命令
Else
当条件表达式不成立时,可以执行的命令
if
实验:修改实验5.3.2.1以下
[/home]# vi sh_2.sh
#!/bin/bash
echo -e "Are you sure?(y/n):\c"
read yn
if [ $yn == "y" || $yn == "n" ] ;then
if [ $yn == "y" ];then
echo "OK,continue"
exit 0
else
echo "Oh,interrupt"
exit 0
fi
else
echo -e "Please enter y or n"
fi
[/home]# ./sh_2.sh
Are you sure?(y/n):y
OK,continue
语法格式3
If [条件判断表达式1 ];then
当条件表达式1成立时,可以执行的命令
Elif [条件判断表达式2 ];then
当条件表达式2成立时,可以执行的命令
Else
当条件表达式1与2均不成立时,可以执行的命令
fi
实验:修改5.3.2.1如下
[/home]# vi sh_3.sh
#!/bin/bash
echo -e "Are you sure?(y/n):\c"
read yn
if [ $yn == "y" ] ;then
echo "OK,continue"
exit 0
elif [$yn == “n” ];then
echo "Oh,interrupt"
exit 0
else
echo -e "Please enter y or n"
fi
[/home]# ./sh_3.sh
Are you sure?(y/n):y
OK,continue
2、case语句
case语句允许进行多重条件选择
语法结构:
case $变量名称 in
第一个变量内容) 
       程序段(满足第一个变量内容)
        ;;
第二个变量内容) 
       程序段(满足第二个变量内容)
        ;;
    
*) 
程序段(均不满足前面的条件下)
       
        ;;
Esac
语法分析:
其执行过程是用“字符串”的值依次与各模式字符串进行比较,如果发现同某一个匹配,那么就执行该模式字符串之后的各个命令,直至遇到两个分号为止。如果没有任何模式字符串与该字符串的值相符合,则不执行任何命令。
  在使用case语句时应注意:
  (1)每个模式字符串后面可有一条或多条命令,其最后一条命令必须以两个分号(即;;)结束。
  (2)模式字符串中可以使用通配符。
  (3) 如果一个模式字符串中包含多个模式,那么各模式之间应以竖线(|)隔开,表示各模式是“或”的关系,即只要给定字符串与其中一个模式相配,就会执行其后的命令表。
  (4)各模式字符串应是惟一的,不应重复出现。并且要合理安排它们的出现顺序。例如,不应将“*”作为头一个模式字符串,因为“*”可以与任何字符串匹配,它若第一个出现,就不会再检查其它模式了。
  (5)case语句以关键字case开头,以关键字esac(是case倒过来写!)结束。
  (6)case的退出(返回)值是整个结构中最后执行的那个命令的退出值。若没有执行任何命令,则退出值为零。
实验:设计一个简单选择菜单,用户输入不同选择时,执行不同动作
[root@localhost home]# vi sh.sh
#!/bin/bash
echo " a) choice a"
echo " b) choice b"
echo " c) choice c"
echo -e "Please enter your choice:\c"
read menu_choice
case "$menu_choice" in
a) echo "you choice a" ;;
b) echo "you choice b" ;;
c) echo "you choice c" ;;
*) echo "sorry,choice not exist" ;;
esac
运行脚本执行如下:
[root@localhost home]# ./sh.sh
a) choice a
b) choice b
c) choice c
Please enter your choice:c
you choice c
[root@localhost home]# ./sh.sh
a) choice a
b) choice b
c) choice c
Please enter your choice:dfjsk
sorry,choice not exist
3.4.3.2.3 循环结构
循环可以不断执行某个程序段,直到用户设置的条件实现为止。下面介绍几种常用的循环结构。
1、while do done语句
语法结构:
While [ 条件判断表达式 ]
do
程序段
done
语法分析:
当条件判断表达式成立时,就进行循环,直到条件判断表达式不成立才停止。
实验:
[root@localhost home]# ./sh.sh
#!/bin/bash
echo " a) choice a"
echo " b) choice b"
echo " c) choice c"
echo -e "Please enter your choice:\c"
read menu_choice
while [ "$menu_choice" != "a" ] && [ "$menu_choice" != "b" ] && [ "$menu_choice" != "c" ]
do
echo -e "Please enter your choice(a/b/c) to stop this program:\c"
read menu_choice
done
脚本运行如下:
[root@localhost home]# ./sh.sh
a) choice a
b) choice b
c) choice c
Please enter your choice:k
Please enter your choice(a/b/c) to stop this program :e
Please enter your choice(a/b/c) to stop this program :a
2、until do done语句。
语法结构:
Until [ 条件判断表达式 ]
do
程序段
done
语法分析:
与前面的while do done 刚好相反,它说的是“当条件判断表达式成立时,就终止循环,否则就持续执行循环的程序段”
实验:用until do done 结构修改上一实验以实现相同功能
[root@localhost home]# vi sh.sh
#!/bin/bash
echo " a) choice a"
echo " b) choice b"
echo " c) choice c"
echo -e "Please enter your choice:\c"
read menu_choice
until [ "$menu_choice" == "a" ] || [ "$menu_choice" == "b" ] || [ "$menu_choice" == "c" ]
do
echo -e "Please enter your choice(a/b/c) to stop this program:\c"
read menu_choice
done
脚本运行如下:
[root@localhost home]# ./sh.sh
a) choice a
b) choice b
c) choice c
Please enter your choice:k
Please enter your choice(a/b/c) to stop this program :e
Please enter your choice(a/b/c) to stop this program :a
读者可以从以上两个实验来好好体会下两种结构间的区别。
3、for do done语句
语法结构:
for [ 条件判断表达式 ]
do
程序段
done
语法分析:
for语句是最常用的建立循环结构的语句,其条件判断表达式更是形式多样。同while一样,是当满足条件判断时,就进行循环,直到条件不成立才停止。
实验1:用for结构实现计算1+2+3+…..+100之和
[root@localhost home]# vi sh.sh
#!/bin/bash
s=0
for ((i=1;i<=100;i=i+1))
do
s=$(($s+$i))
done
echo "the result of '1+2+3+...+100' is ==> $s"
脚本运行如下:
[root@localhost home]# ./sh.sh
the result of '1+2+3+...+100' is ==> 5050
实验2:用一个变量实现多次赋值
#!/bin/bash
for day in Monday Wednesday Friday Sunday
do
echo "$day"
done
运行脚本如下:
[root@localhost home]# ./sh.sh
Monday
Wednesday
Friday
Sunday
程序分析:
 其执行过程是,变量day依次取值表中各字符串,即第一次将“Monday”赋给day,然后进入循环体,执行其中的命令,显示出Monday。第二次将“Wednesday”赋给day,然后执行循环体中命令,显示出Wednesday。依次处理,当day把值表中各字符串都取过一次之后,下面day的值就变为空串,从而结束for循环。因此,值表中字符串的个数就决定了for循环执行的次数。在格式上,值表中各字符串之间以空格隔开。
实验3:(用for in 结构来实现多个脚本依次执行的功能)