结构化命令case和for、while循环
1、case 流程控制语句
case
是一种流程控制语句,通常用于根据不同的条件值执行不同的代码块。它的语法如下:
case expression in
pattern1)
# 在匹配 pattern1 时执行的代码
;;
pattern2)
# 在匹配 pattern2 时执行的代码
;;
pattern3)
# 在匹配 pattern3 时执行的代码
;;
*)
# 如果没有匹配的模式时执行的代码
;;
esac
-
expression
是需要进行匹配的表达式或变量。 -
pattern1
、pattern2
、pattern3
等是可能的模式,可以是常量字符串或使用通配符的模式。 -
;;
用于标记每个模式下的代码块的结束。 -
*)
是一个通配符模式,用于匹配所有未被之前的模式匹配的情况。
例:简单的apache启动脚本
#!/bin/bash
######################################
#filename:httpd start scripts
#author:kc
#date:2023-09-01
######################################
cat << EOF
####################
# 1.start #
# 2.statas #
# 3.stop #
# 4.exit #
####################
EOF
read -p "please input your choose:" OP
case $OP in
1)
systemctl start httpd
;;
2)
systemctl status httpd
;;
3)
systemctl stop httpd
;;
4)
exit
;;
*)
echo error
;;
esac
2、for循环语句
for
循环用于迭代一个列表或范围,并对每个元素执行一组命令。Shell支持不同种类的for
循环,最常用的有两种:for-in
循环和 for
循环。
1. for-in
循环
for-in
循环用于迭代一个列表中的元素。以下是基本语法:
#!/bin/bash
for variable in list
do
# 在循环内执行的命令
done
-
variable
是一个变量,用于存储列表中的每个元素。 -
list
是要迭代的元素列表,可以是一组字符串、文件列表等。
示例:
#!/bin/bash
fruits=("apple" "banana" "cherry")
for fruit in "${fruits[@]}"
do
echo "水果: $fruit"
done
上述代码将迭代 fruits
数组中的每个元素,并将其打印出来。
2. for
循环
for
循环用于迭代一系列数字(通常是一个范围)。以下是基本语法:
for (( init; condition; increment ))
do
# 在循环内执行的命令
done
-
init
是初始化语句,通常用于设置一个计数器。 -
condition
是循环的条件,循环会一直执行直到条件为假。 -
increment
是在每次迭代后更新计数器的语句。
示例:
#!/bin/bash
for (( i=1; i<=5; i++ ))
do
echo "迭代次数: $i"
done
上述代码将循环迭代5次,并在每次迭代中打印出迭代次数。
除了上述两种基本循环,还可以使用 seq
命令来生成数字序列并用于循环。例如:
#!/bin/bash
for i in $(seq 1 5)
do
echo "迭代次数: $i"
done
这将产生与前面示例相同的输出。
无论是 for-in
循环还是 for
循环,都可以用于处理各种迭代任务,例如文件列表的处理、命令的多次执行等。
3、IFS 字段分隔符
字段分隔符 IFS
(Internal Field Separator)是一个特殊的环境变量,用于指定字段(单词)在字符串中的分隔符。默认情况下,IFS
包含空格、制表符和换行符,这意味着Shell会将这些字符视为字段分隔符,并用它来拆分字符串。你可以自定义 IFS
的值,以适应你的需求。
1. 默认的 IFS
默认情况下,IFS
包含以下字符:
-
空格()
-
制表符(
\t
) -
换行符(
\n
)
这意味着当你使用命令像 read
或字符串分割操作时,Shell会使用这些字符来分割输入的字符串。
#!/bin/bash
string="apple banana cherry"
IFS=" " # 设置IFS为单个空格
read -ra fruits <<< "$string"
for fruit in "${fruits[@]}"; do
echo "$fruit"
done
在上面的示例中,我们将 IFS
设置为单个空格,然后使用 read
命令将字符串 $string
分割成一个数组,并遍历输出。
2. 自定义 IFS
你可以根据需要自定义 IFS
的值,以适应不同的分割字符。例如,如果你有一个以逗号分隔的字符串,你可以将 IFS
设置为逗号来分割它:
#!/bin/bash
csv="apple,banana,cherry"
IFS="," # 设置IFS为逗号
read -ra fruits <<< "$csv"
for fruit in "${fruits[@]}"; do
echo "$fruit"
done
这将把 $csv
字符串分割成一个逗号分隔的数组。
请注意,自定义 IFS
时要小心,确保它适用于你的特定需求。当不再需要自定义 IFS
时,最好将其还原为默认值,以免影响其他部分的脚本。例如,可以将 IFS
重新设置为默认值:
IFS=$' \t\n' # 将IFS还原为默认值
4、while循环语句
while
循环语句用于在条件满足的情况下重复执行一组命令。循环会一直执行,直到条件不再满足。以下是 while
循环的基本语法:
while [ condition ]
do
# 在循环内执行的命令
done
-
condition
是一个条件表达式,通常包含了一个命令、比较操作符和值。如果condition
的结果为真(返回退出状态码为0),则继续执行循环内的命令;如果为假(返回退出状态码为非零),则退出循环。 -
下面是一个简单的示例,演示了如何使用 while
循环来打印数字从1到5:
#!/bin/bash
counter=1
while [ $counter -le 5 ]
do
echo "Counter is $counter"
((counter++)) # 增加计数器的值
done
在上面的示例中,counter
变量用于追踪循环的迭代次数。while
循环的条件是 [ $counter -le 5 ]
,它检查 counter
是否小于或等于5。只要条件满足,循环就会继续执行,并在每次迭代中打印当前计数器的值。迭代完成后,计数器递增,循环继续,直到条件不再满足。
在实际脚本中,while
循环通常与条件和用户输入等交互操作一起使用,以便在满足特定条件时执行一组命令,例如文件处理、数据处理等任务。
5、嵌套循环
在Shell脚本中,你可以嵌套循环,这意味着你可以在一个循环内包含另一个循环。嵌套循环非常有用,因为它们允许你在内部循环中执行更复杂的操作,而外部循环控制循环的重复次数。以下是一个示例,演示了如何使用嵌套循环:
#!/bin/bash
# 外部循环控制行数
for (( i=1; i<=3; i++ ))
do
echo "行 $i"
# 内部循环控制列数
for (( j=1; j<=4; j++ ))
do
echo -n " 列 $j"
done
echo # 换行以分隔行
done
在这个示例中,我们有一个外部 for
循环,用于控制行数(1 到 3)。每次外部循环迭代时,内部有一个 for
循环,用于控制列数(1 到 4)。内部循环在每次外部循环迭代时都会执行一遍。
运行这个脚本将生成如下输出:
行 1 列 1 列 2 列 3 列 4
行 2 列 1 列 2 列 3 列 4
行 3 列 1 列 2 列 3 列 4
这个示例展示了嵌套循环的基本概念,但你可以根据需要调整外部和内部循环的计数器以及执行的命令来实现更复杂的操作。嵌套循环常用于处理多维数据、矩阵、文件处理等情况,其中需要同时控制行和列。
6、break和continue
break
和 continue
关键字来控制循环的行为:
-
break
:-
break
用于立即退出循环,不再执行循环中剩余的代码。 -
通常,
break
用于在满足某个条件时退出循环,以提前结束循环迭代。
-
示例:
#!/bin/bash
for i in {1..5}
do
if [ $i -eq 3 ]
then
echo "遇到3,退出循环"
break
fi
echo "迭代: $i"
done
在上面的示例中,当循环变量 i
的值等于3时,break
被触发,循环被提前退出。
-
continue
:-
continue
用于跳过当前迭代并继续下一次循环迭代。 -
通常,
continue
用于在某些条件下跳过特定的迭代。
-
示例:
#!/bin/bash
for i in {1..5}
do
if [ $i -eq 3 ]
then
echo "跳过3,继续下一次迭代"
continue
fi
echo "迭代: $i"
done
在上面的示例中,当循环变量 i
的值等于3时,continue
被触发,跳过了值为3的迭代,然后继续下一次迭代。
break
和 continue
可以在各种循环中使用,包括 for
循环和 while
循环,以控制循环的流程。它们通常用于根据特定条件来管理循环的行为。
7、shift左移命令
shift
命令用于左移命令行参数列表(或位置参数列表)中的参数。它将删除第一个参数,并将其他参数依次左移一个位置。shift
命令通常用于处理命令行参数或选项。
以下是 shift
命令的基本语法:
shift [n]
-
n
是一个可选的参数,表示要左移的位置数。如果不指定n
,则默认为1。
示例:
#!/bin/bash
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "第三个参数: $3"
shift # 默认左移一个位置
echo "左移后的参数列表:"
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "第三个参数: $3"
在上面的示例中,我们首先打印出前三个命令行参数的值,然后使用 shift
命令左移了一个位置,将第一个参数删除,并将其他参数左移一个位置。然后我们再次打印参数,可以看到参数列表已经左移了一个位置。
当需要处理多个命令行参数或选项时,shift
命令很有用,因为它允许你依次处理参数列表而不必手动访问每个参数。可以在循环中使用 shift
命令来遍历参数列表,以执行相应的操作。
假设你运行这个脚本,并传递了一些参数:
./myscript.sh apple banana cherry
脚本会首先打印出传递的参数:
第一个参数: apple
第二个参数: banana
第三个参数: cherry
然后,通过使用shift
命令左移一个位置,它会删除第一个参数,并将其他参数左移。再次打印参数将显示:
左移后的参数列表:
第一个参数: banana
第二个参数: cherry
第三个参数:
如你所见,第一个参数"apple"被删除了,而其他参数左移了一个位置。这就是shift
命令在处理命令行参数时的用法示例。
示例:通过传参做加法运算
1 #!/bin/bash
2 if [ $# -le 0 ];then
3 echo "您没有输入参数"
4 fi
5 sum=0
6 while [ $# -gt 0 ];do
7 sum=$(($sum+$1))
8 shift
9 done
10 echo "result is $sum"
8、实战
例:打包/var/log
目录下的log
文件,并复制保存在/opt/backup/
目录下
#/bin/bash
src=/var/log
des="/opt/backup/$(date +%F)"
if
[ ! -d "$des" ];then
mkdir -p "$des"
fi
for i in `find $src -name '*.log'`
do
tar -czf "$i.tar.gz" "$i"
done
find $src -name "*.tar.gz" -exec mv {} $des \;
ls -lh $des
echo "Creating directory: $des"
echo "The scripts exec end ,Files tar sucessfully!"
例:99乘法表
#!/bin/bash
for i in `seq 9`
do
for j in `seq $i`
do
printf "%d * %d = %d\t" "$i" "$j" "$((i*j))"
#echo -n "$i * $j = $((i*j)) "
if [ $i -eq $j ];then
echo
fi
done
done
例:判断192.168.52.0
网段主机是否开机
1 #!/bin/bash
2 i=1
3 for ((i=1;i<10;i++))
4 do
5 ping -c 3 192.168.52.$i &> /dev/null
6 if [ $? -ne 0 ];then
7 echo "192.168.52.$i is shutdown"
8 fi
9 done
例:批量创建用户
1 #!/bin/bash
2 for i in xuegodc{1..10}
3 do
4 useradd $i
5 pass=$(echo $(date +%s)|md5sum|cut -c 1-8)
6 sleep 1
7 echo "$i:$pass" >> /tmp/passwd.log
8 echo $pass|passwd --stdin $i > /dev/null 2>&1
9 if [ $? -eq 0 ];then
10 echo "Create user $i successfully!"
11 else
12 echo "Create user $i is failed!"
13 fi
14 done
例:批量删除用户
1 #!/bin/bash
2 for i in xuegodc{1..10}
3 do
4 if id $i > /dev/null;then
5 userdel -r $i
6 sleep 1
7 if [ $? -eq 0 ];then
8 echo "User $i deleted successfully!"
9 else
10 echo "Faild to delete user $i"
11 fi
12 fi
13 done
例:交互式创建用户
1 #!/bin/bash
2 while :
3 do
4 read -p "Please enter prefix & password &num:" prefix password num
5 printf "user information:
6 ************************
7 user prefix : $prefix
8 password : $password
9 num : $num
10 ************************
11 "
12 read -p "Are you sure?{Y/N}" action
13 if [ "$action" == "Y" ] || [ "$action" == "y" ];then
14 for i in $( seq $num )
15 do
16 user=${prefix}${i}
17 id $user &> /dev/null
18 if [ $? -ne 0 ] ;then
19 useradd $user
20 echo "$password" |passwd --stdin $user &> /dev/null
21 if [ $? -eq 0 ];then
22 echo -e "\033[31m$user\033[m creat"
23 fi
24 else
25 echo "user $user exist"
26 fi
27 done
28 break
29 elif [ "$action" == "N" ] || [ "$action" == "n" ];then
30 continue
31 fi
32 done
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤