零基础Linux操作基础小白快速掌握Shell脚本--流程控制和循环

1.1 条件选择

1.1.1 选择执行if语句
if结构:
[root@ansible-salve1 shell]# help if
if: if 条件; then 命令; [ elif 命令; then 命令; ]... [ else 命令; ] fi
    根据条件执行命令。
    
    `if COMMANDS'列表被执行。如果退出状态为零,则执行`then COMMANDS' 
    列表。否则按顺序执行每个 `elif COMMANDS'列表,并且如果它的退出状态为
    零,则执行对应的 `then COMMANDS' 列表并且 if 命令终止。否则如果存在的
    情况下,执行 `else COMMANDS'列表。整个结构的退出状态是最后一个执行
    的命令的状态,或者如果没有条件测试为真的话,为零。
    
    退出状态:
    返回最后一个执行的命令的状态。
[root@ansible-salve1 shell]# 
1.1.1.1 单分支
if [ 条件判断式 ];then
	命令
fi 

或者

if [ 条件判断式 ]
  then
   命令
fi
1.1.1.2 双分支

if [ 条件判断式 ]
  then
    命令
else
   命令
fi
1.1.1.3 多分支
if [ 条件判断式1 ]
 then
  命令
elif [ 条件判断式2 ]
 then 
  命令
...
...
else
 命令
fi

案列:

#!/bin/bash
read -p "请输入你的名字:" name
echo "Hello, $name !"
read -p "请输入你的性别(男/女):" gender
if [ "$gender" = "男" ]; then
    echo "尊敬的先生!"
elif [ "$gender" = "女" ]; then
    echo "尊敬的女士!"
else
    echo "无效的性别输入。"
fi

说明:

  • 多个if条件时,逐个条件进行判断,第一次遇见为“真”条件时,执行其分支,而后结束整个if语句

  • if语句可嵌套

1.1.2条件判断case语句
不支持正则表达式

格式:

#!/bin/bash
case $1 in
[0-9])
        command1
;;      
[a-z])
        command2
;;      
        command3
;;
esac


 

[root@ansible-salve1 shell]# help case
case: case 词 in [模式 [| 模式]...) 命令 ;;]... esac
    基于模式匹配来执行命令。
    
    基于 PATTERN 模式匹配的词 WORD,有选择的执行 COMMANDS 命令。
    `|' 用于分隔多个模式。
    
    退出状态:
    返回最后一个执行的命令的状态。
[root@ansible-salve1 shell]# 
case 变量引用 in
PAT1)
	分支1
	;;
PAT2)
	分支2
	;;
...
*)
	默认分支
	;;
esac

case支持glob风格的通配符

*: 任意长度任意字符
?: 任意单个字符
[]: 指定范围内的任意单个字符
|: 或,如a|b ,a或b

案列:条件1【0-9】输出是数字;条件2【a-z】输出是字母;不满足以上条件时,输出都不是

#!/bin/bash
case $1 in
[0-9])
        echo "number"
;;
[a-z])
        echo "letter"
;;
*)
        echo "out of over rang"
;;
esac

示例:工作选项

#!/bin/bash
cat <<EOF
请选择:
1.备份文件
2.清理日志文件
3.软件升级
4.软件回滚
5.删库跑路
6.输入q退出
EOF
read -p "请输入上面的数字1-5:" n1
case $n1 in
1)
 echo "备份文件"
 ;;
2)
 echo "清理日志"
 ;;
3)
 echo "软件升级"
 ;;
4)
 echo "软件回滚"
 ;;
5)
 echo "删库跑路"
q)
 exit
 ;;
*)
 echo "USAGE: 必须输入菜单中数字1"
 ;;
esac
[root@ansible-salve1 shell]# chmod +x info7.sh 
[root@ansible-salve1 shell]# ./info7.sh 
请选择:
1.备份数据库
2.清理日志文件
3.软件升级
4.软件回滚
5.删库跑路
请输入上面的数字1-5:1
备份成功

2.2 循环

2.2.1 循环执行介绍

将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件

重复运行次数

  • 循环次数事先已知

  • 循环次数事先未知

常见的循环的命令:for,while

#循环的逻辑:程序先进行语句判断,如果为真则执行循环语句,然后再进行语句判断,直至语句判断失败才跳出

6.2.2 for循环

格式1:
 

# 第一种写法
for NAME [in words ...]; do commands;done

# 第二种写法
for 变量 in 列表
	循环体
done

# 第三种写法
for 变量 in 列表
do
	循环体
done
#!/bin/bash
#shell结构:
#for i in  {1..10}
#do
#       command
#done   

#c语言结构:
#for ((i=1;i++;i<=10))
#do
#       command
#done

执行机制:

依次将列表中的元素赋值给”变量名“;每次赋值后即执行一次循环体;直到列表中的元素耗尽,循环结束

案列:

#!/bin/bash
#案列1:
#for i in {1..10}
#do     
#       echo$i
#done
#案列2:
#for i in $(ls / boot)
do
        echo ${i}.$(date +%s)
done    

示例:

[root@ansible-salve1 shell]# for i in 1 2 3 4 5 6 ; do echo i=$i;done
i=1
i=2
i=3
i=4
i=5
i=6
[root@ansible-salve1 shell]# for i in {1..10..2};do echo i=$i;done
i=1
i=3
i=5
i=7
i=9
[root@ansible-salve1 shell]# for i in `seq 10`;do echo i=$i;done
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
i=10
[root@ansible-salve1 shell]# sum=0; for i in `seq 10`;do let sum+=i;done;echo sum=$sum
sum=55
[root@ansible-salve1 shell]# 

for循环列表生成方式

  • 直接给出列表

  • 整数列表

{start..end}
$(seq [start [step]] end)

  • 返回列表的命令

$(COMMAND)

  • 使用glob,如:*.sh
# 示例
[root@ansible-salve1 log]# for FILE in `ls /var/log/*.log`;do ll $FILE;done
-rw-------. 1 root root 0 11月 16 08:15 /var/log/boot.log
-rw------- 1 root root 675624 11月 16 07:48 /var/log/dnf.librepo.log
-rw------- 1 root root 81415 11月 16 07:48 /var/log/dnf.log
-rw------- 1 root root 1208 11月 16 07:38 /var/log/dnf.rpm.log
-rw------- 1 root root 39189 11月 16 07:48 /var/log/hawkey.log
-rw------- 1 root root 775 11月 15 04:46 /var/log/vmware-network.1.log
-rw------- 1 root root 775 11月 15 03:54 /var/log/vmware-network.2.log
-rw------- 1 root root 775 11月 14 21:22 /var/log/vmware-network.3.log
-rw------- 1 root root 775 11月 14 06:54 /var/log/vmware-network.4.log
-rw------- 1 root root 775 11月 14 01:21 /var/log/vmware-network.5.log
-rw------- 1 root root 775 11月 13 21:04 /var/log/vmware-network.6.log
-rw------- 1 root root 775 11月 13 04:59 /var/log/vmware-network.7.log
-rw------- 1 root root 775 11月 12 22:00 /var/log/vmware-network.8.log
-rw------- 1 root root 775 10月 28 21:42 /var/log/vmware-network.9.log
-rw------- 1 root root 775 11月 16 07:28 /var/log/vmware-network.log
-rw-r--r--. 1 root root 80892 11月 16 07:28 /var/log/vmware-vmsvc.log
[root@ansible-salve1 log]# 
  • 变量引用,如: $@, $#,$* 位置参数
# 示例
[root@ansible-salve1 shell]# vim info8.sh 
#!/bin/bash
sum=0;
for i in $@;do
   let sum+=i
 done
 echo sum=$sum
[root@ansible-salve1 shell]# chmod +x info8.sh 
[root@ansible-salve1 shell]# ./info8.sh 1 2 4 5 6 7 9
sum=34
[root@ansible-salve1 shell]# 

示例:打印99乘法表

[root@ansible-salve1 shell]# vim info9.sh 
#!/bin/bash
for i in {1..9};do
        for j in `seq $i`;do
                echo -e "${j}x$i=$((j*i))\t\c "
    done
    echo
done
[root@ansible-salve1 shell]# chmod +x info9.sh
[root@ansible-salve1 shell]# ./info9.sh 
1x1=1	
1x2=2	2x2=4	
1x3=3	2x3=6	3x3=9	
1x4=4	2x4=8	3x4=12	4x4=16	
1x5=5	2x5=10	3x5=15	4x5=20	5x5=25	
1x6=6	2x6=12	3x6=18	4x6=24	5x6=30	6x6=36	
1x7=7	2x7=14	3x7=21	4x7=28	5x7=35	6x7=42	7x7=49	
1x8=8	2x8=16	3x8=24	4x8=32	5x8=40	6x8=48	7x8=56	8x8=64	
1x9=9	2x9=18	3x9=27	4x9=36	5x9=45	6x9=54	7x9=63	8x9=72	9x9=81	
[root@ansible-salve1 shell]# 

生产案例:将指定目录下的所有文件的后缀都进行备份

# 取出文件的后缀名
[root@ansible-salve1 shell]# echo nianling.sh | sed -En 's/^(.*)\.([^.]+)$/\2/p'
sh
# 取出文件的前缀名
[root@ansible-salve1 shell]# echo nianling.sh | sed -En 's/^(.*)\.([^.]+)$/\2/p'
nainling


[root@ansible-salve1 shell]# vim info10.sh 
#!/bin/bash
DIR=/root/shell
cd $DIR
for FILE in *;do
   PRE=`echo $FILE | sed -nr 's/(.*)\.([^.]+)$/\1/p'`
   cp $FILE $PRE.bak
done
[root@ansible-salve1 shell]# chmod +x info10.sh 


试题:要求将目录中YYYY-MM-DD中的所有文件移动到YYYY-MM/DD目录下

 1.创建YYYY-MM-DD,当前日期一年前365天到目前一共365个目录,里面有10个文件,$random.log
 [root@ansible-salve1 ~]# vim mkdir.sh 
#!/bin/bash
for i in {1..365};do
       DIR=`date -d "-$i day" +%F`
       mkdir /data/test/$DIR
       cd /data/test/$DIR
       for n in {1..10};do
	   touch $RANDOM.log
       done
done  

# 2.移动到YYYY-MM/DD下
 [root@ansible-salve1 ~]# mkdir mv.sh
#!/bin/bash
DIR=/data/test
cd $DIR
for DIR in *;do
   YYYY_MM=`echo $DIR | cut -d"_" -f1,2`
   DD=`echo $DIR |cut -d"_" -f3`
   [ -d $YYYY_MM/$DD ] || mkdir -p $YYYY_MM/$DD &> /dev/null
   mv $DIR/*  $YYYY_MM/$DD
done

试题:扫描一个网段192.168.80.0/24,判断输入的网段中主机的在线状态,将在线的主机IP打印出来

[root@ansible-salve1 ~]# vim ip.sh
#!/bin/bash
IP=192.168.80.
for i in `seq 254`;do
    {
    ping -c1 -W1 $IP$i &> /dev/null && echo $IP$i "is up"
    }&
done
wait         

格式2:

双小括号方法,即((…))格式,也可以用于算术运算,双小括号方法也可以使用bash shell 实现C语言风格的变量操作l=10;((l++))

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

说明:

  • 控制变量初始化:仅在运行到循环代码段时执行一次

  • 控制变量的修正表达式:每轮循环结束后会先进行控制变量修正运算,然后在做条件判断

示例:1到100的和

#!/bin/bash
sum=0
for i in {1..100} ;do
   let sum+=i
done
echo sum=$sum

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

示例:九九乘法表

#!/bin/bash
for ((i=1;i<10;i++));do
    for ((j=1;j<=i;j++));do
        echo -e "${j}x$i=$((j*i))\t\c"
    done
        echo
done     

示例:打印三角形

# 直角三角形
#!/bin/bash
for((i=1;i<=10;i++));do
   for((j=1;j<=2*i-1;j++));do
     echo -e '*\c'
     done
    echo
done

# 等腰三角形
#!/bin/bash
for((i=1;i<=10;i++));do
  for((k=1;k<=10-i;k++));do
  echo -e ' \c'
  done
   for((j=1;j<=2*i-1;j++));do
     echo -e '*\c'
     done
    echo
done
2.2.3 while循环
[root@ansible-salve1 shell]# help while
while: while 命令; do 命令; done
    只要测试成功即执行命令。
    
    只要在 `while' COMMANDS 中的最终命令返回结果为0,则
    展开并执行 COMMANDS 命令。
    
    退出状态:
    返回最后一个执行的命令的状态。
[root@ansible-salve1 shell]# 

格式:

while command; do commands;done

while condition;do 循环体 done

说明:

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

进入条件:condition为True

退出条件:condition为False

无限循环

while true;do
    循环体
done

案例1:猜数游戏(娱乐小游戏)

#!/bin/bash
# 脚本生成一个100以内得随机数,提示用户猜数字,根据用户得输入,提示用户猜小了或猜大了,直至用户猜对脚本结束
# RANDOM为系统自带的系统变量,值为0~32767的随机数
# 使用取余算法将随机数变为1~100的随机数
num=$[RANDOM%100+1]
echo $num

# 使用read 提示用户猜数字
# 使用if判断用户猜数字的大小关系:
# -eq(等于),-ne(不等于),-gt(大于),-ge(大于等于),-lt(小于),-le(小于等于)
while :
do 
    read -p "数字炸弹在1~100的随机数,请选择数字:" n
    if [ $n -eq $num ];then
        echo "恭喜,爆炸了"
        exit
    elif [ $n -gt $num ];then
        echo "你猜大了,缩小范围为:0~$n之中"
    else
        echo "你猜小了,缩小范围为$n~100之中"
    fi
done

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值