Linux~之六

条件判断
if语句
条件判断,可嵌套
单分支
if 判断条件;then
条件为真的分支代码
fi
双分支
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi

多分支
if 判断条件1; then
条件为真的分支代码
elif 判断条件2; then
条件为真的分支代码
elif 判断条件3; then
条件为真的分支代码
else
以上条件都为假的分支代码
fi
• 逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句

举例

#!/bin/bash #头文件
read -p "Please input a number: " NumBer #利用read -p 命令来交互式赋值
if [ $NumBer -gt 9 ];then #判断赋予的这个值是否大于9,大于9为真then,执行如下
echo "Big" #为真显示 Bjg
elif [ $NumBer -gt 5 -a $NumBer -le 9 ];then #再次判断大于5小于等于9为真
echo "Middle" #为真显示 Middle
else #除了上面的条件其余的则如下
echo "Small" #显示Small
fi #结束语
exit 0 #执行结束 返回0
!!!这里要注意的是 if 开头必须要 if 结束,[ ] 里面参数必须和中括号之间要有空格
-eq 表示两个整数是否相等(可以为负,不能为浮点数)
-gt 左边的数是否大于右边的数
-ge 大于等于
-lt 小于
-le 小于等于
-ne 不等于
case语句
Shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹 配的命令。case语句格式如下:
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
!!!这里要注意的是变量引用后面必须用单词 in 每一个模式必须以右括号结束 像1)取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;

举例

read -p "type a number: " NumBer #给变量赋值
case $NumBer in #选择匹配符号的值
1) echo one;; #输入的值和它匹配就显示它
2) echo two;; #和上面一样
3) echo three;; #和上面一样
esac #结束语

练习
1、编写一个计算个人所得税脚本,执行该脚本,会请求你输入工资,然后算出需要交的税。标准如下:
小于3000,不用交税
3000<=工资< 6000 税率5%
6000<=工资< 9000 税率8%
9000<=工资< 12000 税率10%
工资>=120000 税率20%
显示税多少,和税后工资

#!/bin/bash
read -p "请输入工资: " gongzi
if [ $gongzi -lt 3000 ];then
geshui=0
elif [ $gongzi -ge 3000 -a $gongzi -lt 6000 ];then
geshui=$(echo ${gongzi}*.05 |bc)
elif [ $gongzi -ge 6000 -a $gongzi -lt 9000 ];then
geshui=$(echo ${gongzi}*.08 |bc)
elif [ $gongzi -ge 9000 -a $gongzi -lt 12000 ];then
geshui=$(echo ${gongzi}*.1 |bc)
else
geshui=$(echo ${gongzi}*.2 |bc)
fi
echo "您的个税为: $geshui"
echo "您的税后工资为: $(echo $gongzi-$geshui |bc)"
exit 0

2、编写一个脚本,实现执行它,则会显示当前的日期,格式为如下
2018年06月14日 15时30分18秒 星期四
利用的命令如下:
date "+%Y年%m月%d日 %H时%M分%S秒 星期%w"

#!/bin/bash
w=$(date +%w)
case $w in
1) week="一";;
2) week="二";;
3) week="三";;
4) week="四";;
5) week="五";;
6) week="六";;
*) week="日";;
esac
echo $(date "+%Y年%m月%d日 %H时%M分%S秒") 星期$week

循环
循环执行
将某代码段重复运行多次
重复运行多少次:
循环次数事先已知
循环次数事先未知
有进入条件和退出条件
for, while, until

for 循环
一般格式如下
for 变量名 in 列表;do
循环体
done
执行机制:
依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束

列表生成方式:
(1) 直接给出列表
(2) 整数列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令
$(COMMAND)
(4) 使用glob,如:*.sh
(5) 变量引用;
$@, $*

举例
#!/bin/bash #头文件
for n in 1 2 3 4 5;do #循环 变量n 从1 2 3 4 5 中循环
touch /app/test$n.txt #引用变量 $n 创建test1 test2 ..
done #循环结束

!!!当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。命令可为任何有效的shell命令和语句。in列表可以包含替换、字符串和文件名。
in列表是可选的,如果不用它,for循环使用命令行的位置参数。

练习
给系统中所有uid大于300的用户发一封邮件,内容
"你好,用户xxx, 端午快乐"
发送邮件的命令参考: echo "你好,用户xxx, 端午快乐" |mail -s "端午祝福" xxx
#!/bin/bash
for n in $(cat /etc/passwd |cut -d: -f3);do
if [ $n -gt 300 ];then
UserName=`id -un $n`
echo "你好, 用户$UserName,端午快乐" |mail -s "端午祝福" $UserName
fi
done


while循环
while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为

while condition
do
command
done

CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断条 件
为“true”,则执行一次循环;直到条件测试状态为“false”终止循环
• 因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正
• 进入条件:CONDITION为true
• 退出条件:CONDITION为false

举例
while true;do #循环条件开始,起初没有给结束条件
> echo $a #显示$a的值
> sleep 0.3s #间隔0.3s显示一次
> a=$[$a+1] #a的值进行累加,如本来是0,a=0+1,a就成了1,再次,a=1+1变成了2..
> if [ $a -ge 10 ];then #这里就是结束条件,当a的值大于等于10的时候结束循环
> break #跳出循环命令
> fi #if 的结束符
> done #while循环的结束符

求100以内所有正整数之和
#!/bin/bash
#
declare -i sum=0
declare -i i=1

while [ $i -le 100 ]; do
let sum+=$i
let i++
done

echo "$i"
echo "Summary: $sum."

练习
编写一个依次创建指定用户的脚本,如/root/bin/createuser.sh zhangsan lisi wangsu
#!/bin/bash
while [ $# -gt 0 ];do
if id $1 &> /dev/null ;then
echo "$1 is already exist"
else
useradd $1
echo "$1 created"
fi
shift
done

!!! while循环可用于读取键盘信息

until循环
until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。
语法格式
until CONDITION; do
循环体
done

!!!condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。

举例

until [ $n -gt 9 ];do #n的值大于9的时候不执行
> echo $n #显示变量n
> n=$[$n+1] #变量n累加
> sleep 0.3s #间隔时间显示
> done #结束语

练习

使用 until 命令来输出 0 ~ 9 的数字
#!/bin/bash

a=0

until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done

跳出循环
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。

break
用于循环体中
break [N]:提前结束第N层循环,最内层为第1层

举例

#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done

运行结果
输入 1 到 5 之间的数字:3
你输入的数字为 3!
输入 1 到 5 之间的数字:7
你输入的数字不是 1 到 5 之间的! 游戏结束

continue
用于循环体中
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层

举例

#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
done

运行代码发现,当输入大于5的数字时,该例中的循环不会结束,语句 echo "游戏结束" 永远不会被执行。

!!!continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环


循环控制shift命令
shift [n]
• 用于将参量列表 list 左移指定次数,缺省为左移一次。
• 参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环
遍历位置参量列表时,常用到 shift
• ./doit.sh a b c d e f g h
• ./shfit.sh a b c d e f g h

举例
vim shift.sh #创建脚本

#!/bin/bash
while [ $# -gt 0 ];do
echo $*
shift
done

./shift.sh a b c d e f g #运行脚本,a b c d..赋的值
a b c d e f g
b c d e f g
c d e f g
d e f g
e f g
f g
g


while 循环
while循环的特殊用法(遍历文件的每一行):

while read line; do
循环体
done < /PATH/FROM/SOMEFILE

依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line:

举例
找出其ID号为偶数的所有用户,显示其用户名及ID号

#!/bin/bash

while read line;do
if [ $[`echo $line | cut -d: -f3` % 2] -eq 0 ];then
echo -e -n "username: `echo $line | cut -d: -f1`\t"
echo "uid: `echo $line | cut -d: -f3 `"
fi
done < /etc/passwd #这个是要读取的变量列表

练习
1、扫描/etc/passwd文件每一行,如发现GECOS字段为空,则填充用户名和单位电话为62985600,并提示该用户的GECOS信息修改成功。

#!/bin/bash
while read line ;do
gecos=$(echo $line |cut -d: -f5)
if [ -z "$gecos" ];then
UserName=$(echo $line |cut -d: -f1)
usermod -c "$UserName 62985600" $UserName
echo "$UserName's gecos changed"
fi
done < /etc/passwd

2、编写个脚本,会对系统中已存在的用户进行身份判断,若为centos7,则uid大于1000的用户将判断为comm user,反之判定为sys user, 若为centos6,则uid大于500的用户判断为comm user,反之sys user.输出格式如下
root: sys user
……
liubei: comm user

#!/bin/bash
release=$(cat /etc/centos-release| sed -r 's/.* ([0-9]+)..*/\1/')
while read line; do
uid=$(echo $line | cut -d: -f3)
name=$(echo $line | cut -d: -f1)
if [ $release = 6 -a $uid -lt 500 ] || [ $release = 7 -a $uid -lt 1000 ]; then
echo "$name: sys user"
else
echo "$name: comm user"
fi
done < /etc/passwd
exit 0

3、找出分区利用率大于10%的分区,显示结果如下:
/dev/sda1 will be full : 33%
/dev/sda2 will be full : 99%


#!/bin/bash
df |grep /dev/sd |while read line;do
used=$(echo $line |tr -s " " % |cut -d% -f5)
name=$(echo $line |cut -d" " -f1)
if (( $used > 10 ));then
echo "$name will be full:$used%"
fi
done

for循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式)); do
循环体
done

控制变量初始化:仅在运行到循环代码段时执行一次;
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

举例

求100以内所正整数之和;
#!/bin/bash
#
declare -i sum=0

for ((i=1;i<=100;i++)); do
let sum+=$i
done

echo "Sum: $sum."


select循环
select variable in list
do
循环体命令
done
select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示 PS3 提示
符,等待用户输入
• 用户输入菜单列表中的某个数字,执行相应的命令
• 用户输入被保存在内置变量 REPLY 中

select与case
• select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按ctrl+c 退出循环
• select 经常和 case 联合使用
• 与 for 循环类似,可以省略 in list,此时使用位置参量

举例
#!/bin/bash
PS3="Please choose your fruit: "
select menu in apple banana orange quit;do
case $REPLY in
1)echo "The prise is \$10";;
2)echo "The prise is \$5";;
3)echo "The prise is \$6";;
*)break;;
esac
done

练习
为某餐馆用Shell制作一个点菜系统。
执行脚本,会列出主菜单,如下
请问吃什么?
1) 饭
2) 面
3)饺子
4)不吃

等待用户选择
如选择1,则再问,选择完后报价
1) 炒饭
2)盖饭
3)木桶饭
如选择2,则再问
1)炒面
2)盖面
3)拉面
4)拌面
如选择3,则再问
1)猪肉大葱
2)素三鲜
3)韭菜鸡蛋
每项选择后,最终会报价,如
木桶饭: 10元
如选择4,则退出

#!/bin/bash
PS3="Please choose your food: "
echo "请问吃什么"
caidan() {
select menu in 饭 面 饺子 不吃;do
case $REPLY in
1) select fan in 炒饭 盖饭 木桶饭 返回;do
case $REPLY in
1) echo "炒饭: 10";break 2;;
2) echo "盖饭: 12";break 2;;
3) echo "木桶饭:15";break 2;;
4) caidan;;
esac
done
;;
2) select mian in 炒面 盖面 拉面 拌面 返回;do
case $REPLY in
1) echo "炒面: 10";break 2;;
2) echo "盖面: 12";break 2;;
3) echo "拉面:15";break 2;;
4) echo "拌面: 18";break 2;;
5) caidan;;
esac
done
;;
3) select jiaozi in 猪肉大葱 素三鲜 韭菜鸡蛋 返回;do
case $REPLY in
1) echo "猪肉大葱: 10";break 2;;
2) echo "素三鲜: 12";break 2;;
3) echo "韭菜鸡蛋:15";break 2;;
4) caidan;;
esac
done
;;
4) exit;;
esac
done
}
caidan




信号捕捉trap
trap '触发指令' 信号
自定义进程收到系统发出的指定信号后,将执行触发指令,而不会执行原操作
• trap '' 信号
忽略信号的操作
• trap '-' 信号
恢复原信号的操作
• trap -p
列出自定义信号操作

举例
#!/bin/bash
trap 'echo 停不下来,也杀不死' int term
for ((i=0;i<=100;i++));do
echo $i
sleep 0.5
done
# int 相当于 Ctrl+c



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值