shell脚本编程(六)
https://blog.csdn.net/xiaochenXIHUA/article/details/156865391
一、列表for循环
1.1、列表for循环
bash
#列表for循环的语法
for variable in list #每一次循环,都依次把列表list中的一个值赋给循环变量
do #循环体开始的标志
commands #循环变量每取一次值,循环体就执行一遍
done #循环介绍的标志,返回循环顶部
|--------|---------------------------------------------------------|
| 序号 | 说明 |
| 1 | 列表list可以是【命令替换】【变量名替换】【字符串】和【文件名列表】(可包含通配符),每个列表项以空格间隔。 |
| 2 | for循环执行的次数取决于列表list中单词的个数 |
| 3 | 可以省略【in list】,省略时相当于【in "$@"】 |
[列表for循环注意项]
|--------|---------------------------------------------------------------------------------|
| 序号 | 说明 |
| 1 | 首先将【list】的 item1 赋给variable 执行do和done之间的commands |
| 2 | 然后再将【list】的item2赋给变量variable 执行do和done之间的commands 如此循环,直到list中的所有item值都已经用完 |
[列表for循环流程]

1.2、列表for循环示例一
bash
#列表for循环示例
vi forlist.sh
#【forlist.sh】文件的完整内容:
#!/bin/bash
#filename:forlist.sh
#使用字面字符串列表
echo "======直接输出空格为基础的字符串======"
for x in centos almalinux rockylinux openeuler kylin
do
echo "$x";
done
#若列表项中包含空格必须使用引号括起来
echo "======若列表项中包含空格必须使用引号括起来======"
for y in linux "free bsd" windows "mac os x"
do
echo "$y"
done
echo "======for循环执行命令======"
for z in ls "df -hT" "du -sh *"
do
echo "命令替换方法一【$z】>";eval $z
echo "命令替换方法二【$z】>>";echo "`$z`"
echo "命令替换方法三【$z】>>>";echo "$($z)"
done
#执行脚本
bash forlist.sh
#调试脚本
bash -x forlist.sh




1.3、列表for循环示例二
使用【变量】作为列表:
bash
#列表for循环示例二
vi forlist2.sh
#【forlist2.sh】文件的完整内容:
#!/bin/bash
#filename:forlist2.sh
#使用变量作为列表
i=1;weekdays="Mon Tue Wed Thu Fri Sat Sun"
for day in $weekdays;do
echo "weekday $((i++)) : $day"
done
#直接在双引号中使用单引号将空格内容作为一个整体时没有效果的
echo "============"
oslist="linux 'free bsd' windows 'mac os x'"
for x in $oslist others;do
echo $x
done
#可以手动修改IFS的默认【空格、制表符tab、换行符\n】修改为冒号(:)
echo ">>>>>>>>>>>>>>>>>>>"
OLD_IFS="$IFS"
IFS=:
oslist2="linux:free bsd:windows:mac os x"
for y in $oslist2 others;do
echo $y
done
# 恢复原 IFS
IFS="$OLD_IFS"
#执行脚本
bash forlist2.sh
|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 序号 | 说明 |
| 1 | 在Linux中,IFS(Internal Field Separator)是【内部字段分隔符】,是shell中的一个环境变量,用于控制shell如何将字符串分割成多个字段。 |
| 2 | IFS的默认值: 《1》空格; 《2》制表符(tab); 《3》换行符(\n); bash #以字符形式显示不可见的字符 echo "$IFS" | od -c
|
| 3 | 修改 IFS 会改变 Shell 的字段分割规则,通常建议临时修改,避免影响全局环境。 bash # 保存原 IFS OLD_IFS="$IFS" # 修改 IFS 为冒号 IFS=: # 执行操作 for xin $variable; do echo $x done # 恢复原 IFS IFS="$OLD_IFS" |
[IFS解析]

1.4、列表for循环示例三
这是【不带列表】的for循环
bash
#列表for循环示例三:
vi forlist3.sh
#【forlist3.sh】文件的完整内容
#!/bin/bash
## filename: for3_list.sh
# 使用位置参数变量 $@ 作为 WordList, in $@ 可以省略
[ $# -eq 0 ] && echo "用法:$0 <weekday>" && exit 1
for day ; do
case $day in
[Mm]on)
echo "星期一:${day}" ;;
[Tt]ue)
echo "星期二:${day}" ;;
[Ww]ed)
echo "星期三:${day}" ;;
[Tt]hu)
echo "星期四:${day}" ;;
[Ff]ri)
echo "星期五:${day}" ;;
[Ss]at)
echo "星期六:${day}" ;;
[Ss]un)
echo "星期日:${day}" ;;
*) echo "【${day}】是无效的星期!" ;;
esac
done
#执行脚本
bash forlist3.sh

1.5、列表for循环示例四
这是使用【文件名或目录名】作为列表
bash
#列表for循环示例四
vi forlist4.sh
#【forlist4.sh】文件的完整内容:
#!/bin/bash
#filename:forlist4.sh
#使用文件名或目录名列表作为wordlist
echo "开始将当前目录下的所有大写文件名改为小写"
for fname in * ;do
#使用命令替换生成小写的文件名,赋予新的变量fn
fn=$(echo $fname | tr A-Z a-z)
#若新生成的小写文件名与原文件名不同,改为小写的文件名
if [[ $fname != $fn ]];then mv $fname $fn;fi
#上面的if语句与下面的命令聚合语句等效
#[[ $fname != $fn ]] && mv $fname $fn
#[[ $fname == $fn ]] || mv $fname $fn
echo "将当前目录下的所有大写文件名改为小写【完成】"
done
#执行脚本
mkdir {COFFEEMILK,CK}
touch ckMilk
ls -al
bash forlist4.sh
ls -al


bash
#列表for选好示例四-二
vi forlist4-2.sh
#【forlist4-2.sh】文件完整内容:
#!/bin/bash
#filename:forlist4-2.sh
echo "获取当前目录下所有的zip文件并解压"
for i in *.zip;do
echo $i
j="${i%.zip}" && echo $j
mkdir "$j" && unzip -d "$j" "$i"
echo "===解压【$i】完成==="
done
echo "======获取当前目录下所有的zip文件并解压【完成】======"
#执行脚本
bash forlist4-2.sh

1.6、列表for循环示例五
这是使用【命令的执行结果】作为列表。
bash
#列表for循环示例五
vi forlist5.sh
#【forlist5.sh】文件的完整内容



bash
#列表for循环示例五-二
vi forlist5-2.sh
#【forlist5-2.sh】文件的完整内容:
#!/bin/bash
#filename:forlist5-2.sh
#使用命令替换的结果作为列表(wordlist)
for host in $(cat /etc/hosts);do
if ping -c1 -w2 "${host}" >/dev/null 2>&1;then
echo "Host 【$host】 is active"
else
echo "Host 【$host】 is down!"
fi
done
#执行脚本
bash forlist5-2.sh

1.7、列表for循环示例六
这是使用【数值范围】作为列表。
bash
#列表for循环示例六
vi forlist6.sh
#【forlist6.sh】文件的完整内容
#!/bin/bash
#filename:forlist6.sh
#使用数值范围作为列表(wordlist)
net="192.168.1"
for num in {1..16};do
echo "IPAddress $num:$net.$num"
done
echo "使用包含步长的数值范围作为列表"
for x in {2..12..2};do
echo "Number:$x"
done
#执行脚本
bash forlist6.sh

1.8、列表for循环示例七
批量添加用户
bash
#列表for循环示例七
vi forlist7.sh
#【forlist7.sh】文件的完整内容
#!/bin/bash
## filename: forlist7.sh
# 成批添加50个用户
for x in {1..26} # 或 $(seq 26)
do
useradd user${x}
echo "centos"|passwd --stdin user${x} #stdin是接受echo后面的字符串做为密码,stdin是非交互,直接传入密码,
#passwd默认是要用终端作为标准输入,加上--stdin表示可以用任意文件做标准输入,于是这里用管道作为标准输入
#强制用户在首次登录时需要修改密码
chage -d 0 user${x}
done
1.9、列表for循环示例八
bash
#列表for循环示例八
vi forlist8.sh
#【forlist8.sh】文件的完整内容
#!/bin/bash
## filename: forlist8.sh
# for 语句可嵌套
for i in 1 3 ; do
for j in {1..13} ; do
ip=192.168.$i.$j
if ping -c1 -w2 $ip >/dev/null 2>&1
then
#ssh-keyscan -t rsa,dsa $ip \
# >> ~/.ssh/known_hosts
echo "$ip is active"
else
echo "Host ($ip) is DOWN."
fi
done
done

二、break与continue
|--------|----------------------------------------------------------------------------------------------------------|
| 序号 | 说明 |
| 1 | bash break [n] 《1》用于强行退出当前循环。 《2》若是嵌套循环,则break命令后面可以跟一个数字n,表示退出第n重循环(最里面的为第一重循环)。 |
| 2 | bash continue [n] 《1》用于忽略本次循环的剩余部分,回到循环的顶部,继续下一次循环。 《2》若是嵌套循环,continue命令后面也可以跟一个数字n,表示回到第n重循环的顶部。 |
[break与continue]
bash
#for循环中的break示例
vi for-loop-break.sh
#【for-loop-break.sh】文件的完整内容
#!/bin/bash
#filename:for-loop-break.sh
i=1
for day in Mon Tue Wed Thu Fri;do
echo "weekday $((i++)):$day"
if [ $i -eq 4 ];then
break
fi
done
#执行脚本
bash for-loop-break.sh

bash
#for循环中的cotinue示例
vi for-loop-continue.sh
#【for-loop-continue.sh】文件的完整内容
#!/bin/bash
#filename:for-loop-continue.sh
i=1
for day in Mon Tue Wed Thu Fri Sat Sun;do
echo -n "Day $((i++)):$day"
if (($i==7 || $i==8));then
echo " Weekend"
continue
fi
echo " weekday"
done
for x in {1..12};do
if (($x%2==0));then
continue
else
echo "$x"
fi
done
#执行脚本
bash for-loop-continue.sh

三、C语言型for循环
bash
#C语言型for循环语法
for ((expr1;expr2;expr3)) #执行expr1
do #若expr2的值为真时进入循环,否则退出for循环
commands #执行循环体,之后执行expr3
done #循环结束的标志,返回循环顶部
|--------|----------------------------------|
| 序号 | 说明 |
| 1 | 通常expr1与expr3是算术表达式;expr2是逻辑表达式。 |
| 2 | expr1仅在循环开始之初执行一次。 |
| 3 | expr2在每次执行循环体之前执行一次。 |
| 4 | expr3在每次执行循环体之后执行一次。 |
| 类C语言风格的for循环也被称为【计次循环】,一般用于循环次数已知的情况。 ||
| ||
| C语言型for循环的执行流程: 《1》执行expr1【表达式expr1为循环变量赋初值的语句】; 《2》执行expr2【表达式expr2决定是否进行循环的表达式,当判断expr2退出状态为0执行do和done之间的循环体,当退出状态为非0时将退出for循环执行done后的命令】: ①expr2的值为假时,直接终止循环; ②expr2的值为真时,执行do与done之间的commands; ③执行expr3【表达式expr3用于改变循环变量的语句】,进入下一次循环。如下图所示: ||
[C语言型for循环]

bash
#C语言型for循环示例一
vi for-c.sh
#【for-c.sh】文件的完整内容
#!/bin/bash
#filename:for-c.sh
echo "经典的c语言结构for循环"
for ((i=0;i<10;i++));do
echo "$i"
done
echo "输出10个随机数"
for ((i=1;i<=10;i++));do
echo "random number $i:$RANDOM"
done
echo "双变量操作"
for ((i=1,j=10;i<=5;i++,j=j+5));do
echo "Number $i:$j"
done
#执行脚本
bash for-c.sh

bash
#c语言型for循环示例二
vi for-c2.sh
#【for-c2.sh】文件的完整内容
#!/bin/bash
## filename: for-c2.sh
s=0
for ((i=1;i<=100;i++)) ; do
let s=$s+$i
done
echo sum\(1..100\)=$s
for ((s=0,i=1;i<=100;i++)) ; do
((s+=i)) #s=s+i
done
echo sum\(1..100\)=$s
for ((s=0,i=1;i<=100;s+=i,i++))
do
:
done
echo sum\(1..100\)=$s
#执行脚本
bash for-c2.sh
