循环
for
语法1:
- 不只适合数字,还支持通配符通配文件名等
for NAME [in WORDS ... ] ; do COMMANDS; donefor 变量名(每一次列表的值都会赋给这个变量) in 列表(决定循环体执行的次数);do
循环体(command)
done语法2:
-
只适合数字
-
控制变量初始化:仅在运行到循环代码段时执行一次
-
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
循环体
done
范例
[root@centos ~]# for i in 1 2 3 a b c;do echo i=$i ;done
i=1
i=2
i=3
i=a
i=b
i=c
[root@centos ~]# for i in {1..3};do echo i=$i ;done
i=1
i=2
i=3
[root@centos ~]# for i in {1..3}{a..b};do echo i=$i ;done
i=1a
i=1b
i=2a
i=2b
i=3a
i=3b
[root@centos ~]# for i in {10..1};do echo i=$i ;done
i=10
i=9
i=8
i=7
i=6
i=5
i=4
i=3
i=2
i=1
[root@centos ~]# for i in {10..1..2};do echo i=$i ;done
i=10
i=8
i=6
i=4
i=2
[root@centos ~]# for i in {a..g..2};do echo i=$i ;done
i=a
i=c
i=e
i=g
[root@centos ~]# 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@centos ~]# 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
#支持通配符*,便利整个目录(不支持递归子目录)
for i in *;do ls $i;donefor循环实现计算1到100相加之和
#语法1
sum=0;for i in {1..100};do ((sum+=i));done;echo $sum
或
sum=0;for i in {1..100};do let sum+=i;done;echo $sum
---------------------------------------------------------------------------------
#语法2
for ((sum=0,i=1;i<=100;i++));do ((sum+=i)) ;done; echo $sum
或
for ((sum=0,i=1;i<=100;i++));do let sum+=i ;done; echo $sumfor循环支持位置变量
[root@centos ~]# vim sum.sh
#!/bin/bash
## #********************************************************************
#Author: xiangzheng
#QQ: 767483070
#Date: 2021-10-22
#FileName: sum.sh
#URL: https://www.xiangzheng.vip
#Email: rootroot25@163.com
#Description: The test script
#Copyright (C): 2021 All rights reserved
#********************************************************************
sum=0
for i in $@;do
let sum+=i
done
echo sum=$sum
[root@centos ~]# ./sum.sh 2 4 6
sum=12for循环实现九九乘法表
#语法1
#打印1x9:
for i in {1..9};do
echo -n "${i}x9=$((i*9)) "
done
echo
#打印九九乘法表:
for i in {1..9};do
for j in `seq ${i}`;do
echo -n "${j}x${i}=$((i*j)) "
done
echo
done
#打印九九乘法表(输出结果对齐):
for i in {1..9};do
for j in `seq ${i}`;do
echo -e "${j}x${i}=$((i*j))\t\c"
done
echo
done
---------------------------------------------------------------------------------------
#语法2
for ((i=1;i<=9;i++));do
for ((j=1;j<=i;j++));do
echo -e "${j}x${i}=$((i*j))\t\c"
done
echo
donefor无限循环
for((;;));do echo for;donefor循环嵌套范例
- 注意先后顺序,不同的顺序执行结果则不同
#script
PROXY_HOST="10.0.0.8 10.0.0.18"
IP_LIST="10.0.0.28 10.0.0.38"
function host_down(){
for IP in ${PROXY_HOST};do
for IPLIST in ${IP_LIST};do
for SOCK_NUM in `seq 4`;do #`seq 4`表示4个sock文件的不同命名
echo ${IP} ${IPLIST} ${SOCK_NUM}
done
done
done
}
host_down
#执行结果
10.0.0.8 10.0.0.28 1
10.0.0.8 10.0.0.28 2
10.0.0.8 10.0.0.28 3
10.0.0.8 10.0.0.28 4
10.0.0.8 10.0.0.38 1
10.0.0.8 10.0.0.38 2
10.0.0.8 10.0.0.38 3
10.0.0.8 10.0.0.38 4
10.0.0.18 10.0.0.28 1
10.0.0.18 10.0.0.28 2
10.0.0.18 10.0.0.28 3
10.0.0.18 10.0.0.28 4
10.0.0.18 10.0.0.38 1
10.0.0.18 10.0.0.38 2
10.0.0.18 10.0.0.38 3
10.0.0.18 10.0.0.38 4while
语法
while CONDITION; do COMMANDS; done
while CONDITION; do
循环体
done语法说明
CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环,因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正
进入条件:CONDITION为true
退出条件:CONDITION为false
while无限循环
while true; do
循环体
donewhile循环实现计算1到100相加之和
while read 特殊用法
while 循环的特殊用法,遍历文件或文本的每一行
生产中需要逐行处理的情况可以使用此语句
语法:
while read line; do
循环体
done < /PATH/FROM/SOMEFILE范例:
#交互式
[root@centos ~]# while read -p "姓名:" name;do echo $name;done
姓名:xiang
xiang
姓名:zheng
zheng
#非交互式
[root@centos ~]# vim name.txt
[root@centos ~]# cat name.txt
xiang
zheng
[root@centos ~]# while read -p "姓名:" name;do echo $name;done < name.txt
xiang
zheng
#非交互式2
[root@centos ~]# cat name.txt
xiang
zheng
[root@centos ~]# cat name.txt | while read -p "姓名:" name;do echo $name;done
xiang
zheng范例:访问量检测
until
和while循环正好相反,while循环是为真就会一直执行循环,而until是为假就会一直执行循环
语法
until COMMANDS; do COMMANDS; done
until CONDITION; do
循环体
doneuntil无限循环
until false; do
循环体
Done范例
#如果为0,就执行sleep
until [ $result -eq 0 ] ;do
sleep 1
done循环控制语句:
continue
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
语法:
while CONDITION1; do
CMD1
...
if CONDITION2; then
continue
fi
CMDn
...
done范例:
break
break [N]:提前结束第N层整个循环,最内层为第1层
语法:
while CONDITION1; do
CMD1
...
if CONDITION2; then
break
fi
CMDn
...
done范例1:
sum=0
COLOR='echo -e \033[1;31m'
COLOR2='echo -e \033[1;32m'
END="\033[0m"
while true;do
echo -e "\033[33;1m\c"
cat <<EOF
1) 鲍鱼
2) 满汉全席
3) 龙虾
4) 燕窝
5) 帝王蟹
6) 退出
EOF
echo -e "\033[0m"
read -p "请点菜(1-6): " MENU
case $MENU in
1|4)
$COLOR'菜价: $10'$END
let sum+=10
;;
3|5)
$COLOR'菜价: $20'$END
let sum+=20
;;
2)
$COLOR'菜价: $1000'$END
let sum+=1000
;;
6)
$COLOR2"你点的菜总价格是 $sum"$END
break
;;
*)
echo "点错了,没有这道菜"
;;
esac
$COLOR2"你点的菜总价格是 $sum"$END
done范例2:
NUM=$[RANDOM%10]
while read -p "输入 0-9 之间的数字: " INPUT ;do
if [ $INPUT -eq $NUM ];then
echo "恭喜你猜对了!"
break
elif [ $INPUT -gt $NUM ];then
echo "数字太大了,重新猜!"
else
echo "数字太小了,重新猜!"
fi
doneshift
- shift [n] 用于将参量列表 list 左移指定次数,缺省为左移一次。
- 参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。
- while 循环遍历位置参量列表时,常用到 shift
在Shell脚本中,shift是一个用于处理命令行参数的内建命令。它用于将位置参数(命令行参数)向左移动一个位置,并丢弃原来的第一个位置参数。这样,原来的第二个参数就成为新的第一个参数,依此类推。shift命令通常用于循环处理命令行参数,或者在函数中处理函数参数。
注意事项:
- 需要注意的是,使用
shift命令后,原来的第一个位置参数将不再可用。如果需要保留原始的位置参数,可以将其保存到其他变量中,以备后续使用。
shift 语法
shift [n]n是一个可选的整数参数,指定要向左移动的位置参数的个数。- 如果不提供
n,默认为1,即向左移动一个位置参数。
范例一
#!/bin/bash
## 循环处理命令行参数
while [ "$1" != "" ]; do
echo "参数: $1"
shift
done- 上述脚本将打印出传递给脚本的所有位置参数,并使用
shift命令逐个处理它们。 - 每次
shift命令执行后,位置参数向左移动一个位置,直到没有剩余的位置参数为止。
以下是一个示例的输出,假设脚本名为script.sh,并且执行了以下命令:
$ ./script.sh arg1 arg2 arg3输出将是:
参数: arg1
参数: arg2
参数: arg3- 在每次迭代中,
shift命令将当前的第一个位置参数移除,而后续的位置参数则依次前移。 - 因此,循环内的
echo语句每次都打印出当前的第一个位置参数。
范例二
- 利用$1和shift,创建多个账号。
## vim shift.sh
PASS=12345
while [ "$1" ];do
useradd $1 && echo is created || echo $1 is exist
echo $PASS | passwd --stdin $ &> /dev/null
shift
done
## bash shift.sh haha xixi lala
is created
is created
is created
## getent passwd
...
haha:x:1004:1004::/home/haha:/bin/bash
xixi:x:1005:1005::/home/xixi:/bin/bash
lala:x:1006:1006::/home/lala:/bin/bash
## bash shift.sh haha xixi lala
useradd: user 'haha' already exists
haha is exist
useradd: user 'xixi' already exists
xixi is exist
useradd: user 'lala' already exists
lala is exist范例三
- 假设:
./script.sh -u -h ftp.example.com -a username -p password -f file.txt
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-u|--upload) # upload mode
MODE="upload"; shift
;;
-d|--download) # download mode
MODE="download"; shift
;;
-h|--host) # FTP server address
FTP_HOST="$2"; shift 2
;;
-a|--username) # non-anonymous login username
FTP_USER="$2"; shift 2
;;
-p|--password) # non-anonymous login password
FTP_PASS="$2"; shift 2
;;
-s|--subdir) # sub directory on FTP server
SUB_DIR="$2/"; shift 2
;;
-x|--proxy) # proxy server <host>:<port>
PROXY="$2"; shift 2
;;
-f|--file) # filename to upload or download
FILE="$2"; shift 2
;;
-*) # unknown options
echo -e "Unknown option: $1\nTry '$0 --help' for more information." >&2; exit 1
;;
*) # positional arguments
echo -e "Unknown argument: $1\nTry '$0 --help' for more information." >&2; exit 1
;;
esac
done这段代码是一个处理命令行参数的脚本片段,它使用了while循环和case语句来逐个解析命令行参数,并将它们赋值给相应的变量。
让我们逐行解释这段代码的含义:
while [[ $# -gt 0 ]]; do这行代码使用了while循环,条件是命令行参数的个数($#)大于0。这样可以确保在还有未处理的命令行参数时,循环会一直执行。
key="$1"将当前的第一个命令行参数(即关键字)赋值给变量key。
case $key in开始case语句,根据变量key的值进行匹配。
-u|--upload) # upload mode
MODE="upload"; shift
;;如果key的值匹配-u或--upload,则表示是上传模式。将MODE变量设置为"upload",然后执行shift命令将命令行参数向左移动一个位置。
-d|--download) # download mode
MODE="download"; shift
;;如果key的值匹配-d或--download,则表示是下载模式。将MODE变量设置为"download",然后执行shift命令将命令行参数向左移动一个位置。
-h|--host) # FTP server address
FTP_HOST="$2"; shift 2
;;如果key的值匹配-h或--host,则表示是FTP服务器地址。将FTP_HOST变量设置为下一个位置参数的值(即FTP服务器地址),然后执行shift命令将命令行参数向左移动两个位置。
类似地,后续的-a|--username、-p|--password、-s|--subdir、-x|--proxy和-f|--file都是匹配不同的选项,并将相应的变量赋值。
-*) # unknown options
echo -e "Unknown option: $1\nTry '$0 --help' for more information." >&2; exit 1
;;如果key以-开头但不匹配已知选项,则表示是未知选项。脚本会打印错误消息,并以非零退出状态码退出。
*) # positional arguments
echo -e "Unknown argument: $1\nTry '$0 --help' for more information." >&2; exit 1
;;如果key不匹配任何选项,则表示是位置参数。脚本会打印错误消息,并以非零退出状态码退出。
esac结束case语句。
done结束while循环。
通过这段代码,可以解析命令行参数并将其分配给相应的变量。例如,如果执行以下命令:
./script.sh -u -h ftp.example.com -a username -p password -f file.txt根据给定的命令行参数,下面是代码的执行过程和变量的赋值:
- 循环开始,命令行参数个数为7(包括脚本名称)。
- 第一次迭代:
key被赋值为-u。case语句匹配到-u|--upload,MODE被设置为"upload"。shift命令将命令行参数向左移动一个位置,此时命令行参数个数变为6。
- 第二次迭代:
key被赋值为-h。case语句匹配到-h|--host,FTP_HOST被设置为"ftp.example.com"。shift命令将命令行参数向左移动两个位置,此时命令行参数个数变为4。
- 第三次迭代:
key被赋值为-a。case语句匹配到-a|--username,FTP_USER被设置为"username"。shift命令将命令行参数向左移动两个位置,此时命令行参数个数变为2。
- 第四次迭代:
key被赋值为-p。case语句匹配到-p|--password,FTP_PASS被设置为"password"。shift命令将命令行参数向左移动两个位置,此时命令行参数个数变为0。
- 循环结束,没有剩余的命令行参数。
在以上执行过程中,通过case语句的匹配,脚本将识别和处理各种选项和相应的参数。此外,如果出现未知选项或位置参数,脚本会打印错误消息并退出。
最后,根据处理命令行参数的结果,可以使用相应的变量(如MODE、FTP_HOST、FTP_USER、FTP_PASS和FILE)进行后续操作,比如根据模式连接FTP服务器并上传或下载文件。
那么为什么其中有些是 shift 2 有的是 shift 呢?
在这段代码中,shift命令的参数表示要向左移动的位置参数的个数。有些选项需要移动两个位置参数,而有些只需要移动一个位置参数。
当一个选项需要处理一个附加的参数时,比如-h、-a、-p、-s、-x和-f,它们的值紧跟在选项后面。因此,为了将这些选项及其参数正确地从命令行参数中移除,shift命令需要移动两个位置参数。
举个例子,当匹配到-h|--host选项时,需要获取FTP_HOST的值,并将该选项及其参数从命令行参数中移除。因此,shift 2会移动两个位置参数:选项本身的位置参数和其后的参数的位置参数。
而对于那些不需要处理附加参数的选项,比如-u和-d,它们本身就是一个完整的选项。因此,在匹配到这些选项时,只需要将选项本身从命令行参数中移除,所以只需要执行shift命令移动一个位置参数。
通过根据选项需要处理的参数个数来决定使用shift还是shift 2,可以确保选项及其参数都被正确处理并从命令行参数中移除。
—
shell中的循环有哪些方式
在 shell 中,有多种不同的循环方式可供选择,下面是其中几种:
- for 循环:
for 循环通常用于遍历一系列值或文件名,可以使用以下语法:
bashCopy codefor var in list
do
command1
command2
...
done
其中,list 可以是一系列值或文件名,command1、command2 等是在每次循环时执行的命令,var 是一个变量,用于存储当前循环中的值或文件名。
- while 循环:
while 循环可以在某个条件为真时执行一系列命令,可以使用以下语法:
while condition
do
command1
command2
...
done
其中,condition 是一个用于测试的条件表达式,command1、command2 等是在每次循环时执行的命令。
- until 循环:
until 循环与 while 循环类似,但是只有当条件为假时才会执行一系列命令,可以使用以下语法:
bashCopy codeuntil condition
do
command1
command2
...
done
其中,condition 是一个用于测试的条件表达式,command1、command2 等是在每次循环时执行的命令。
- select 循环:
select 循环通常用于从一系列值中选择一个,可以使用以下语法:
csharpCopy codeselect var in list
do
command1
command2
...
done
其中,list 是一系列值,var 是一个变量,用于存储用户选择的值,command1、command2 等是在每次循环时执行的命令。
以上是 shell 中常用的几种循环方式,它们各有不同的用途和语法。
for 循环的语法有哪些,并展示几个范例
在 shell 中,for 循环有以下两种语法:
- 遍历一组值:
bashCopy codefor variable in value1 value2 ... valuen
do
command1
command2
...
done
其中,variable 是循环变量,value1 value2 ... valuen 是要遍历的一组值,command1、command2 等是在每次循环时执行的命令。
例如,下面的示例循环遍历了一组数字:
bashCopy codefor i in 1 2 3 4 5
do
echo $i
done
输出结果为:
Copy code1
2
3
4
5
- 遍历一个目录中的文件:
bashCopy codefor variable in directory/*
do
command1
command2
...
done
其中,variable 是循环变量,directory/* 是要遍历的目录中的所有文件,command1、command2 等是在每次循环时执行的命令。
例如,下面的示例循环遍历了当前目录下的所有文件:
bashCopy codefor file in *
do
echo $file
done
输出结果为当前目录下的所有文件名。
另一个示例是循环遍历指定目录下的所有文件,并打印出每个文件的类型:
bashCopy codefor file in /path/to/directory/*
do
if [ -f "$file" ]; then
echo "$file is a regular file"
elif [ -d "$file" ]; then
echo "$file is a directory"
else
echo "$file is not a regular file or directory"
fi
done
以上是 for 循环的两种常见语法以及一些示例,可以根据具体的需求和场景选择不同的方式。
while 循环的语法有哪些,并展示几个范例
在 shell 中,while 循环有以下两种语法:
- 使用命令输出来控制循环:
bashCopy codewhile command
do
command1
command2
...
done
其中,command 是一个输出结果为 true 或 false 的命令,command1、command2 等是在每次循环时执行的命令。
例如,下面的示例会循环读取用户输入的数字,直到输入的数字等于 0:
bashCopy codewhile true
do
read -p "Enter a number (0 to exit): " num
if [ $num -eq 0 ]; then
break
fi
echo "You entered: $num"
done
- 使用条件表达式来控制循环:
bashCopy codewhile [ condition ]
do
command1
command2
...
done
其中,condition 是一个用于测试的条件表达式,command1、command2 等是在每次循环时执行的命令。
例如,下面的示例循环打印数字 1 到 5:
bashCopy codenum=1
while [ $num -le 5 ]
do
echo $num
num=$((num+1))
done
输出结果为:
Copy code1
2
3
4
5
另一个示例是循环读取一个文件中的内容,并在每一行前加上行号:
bashCopy codefilename="file.txt"
line=1
while read -r content
do
echo "$line: $content"
line=$((line+1))
done < "$filename"
以上是 while 循环的两种常见语法以及一些示例,可以根据具体的需求和场景选择不同的方式。