Linux从入门到精通系列之SHELL编程循环语句语法及实例详解(forwhileuntil)
前言
Shell作為一種腳本編程語言,同樣了包含了循環,分支等其他程序控制結構,從而能夠輕松完成更加復雜、強大的功能。我們今天就來認識for、while、case語句的具體應用。
插個小廣告吧,雖然我一開始是拒絕的,課程的內容質量還是可以的,喜歡的小伙伴根據自身需求自行訂閱
相關教程傳送門:即學即用的Linux核心技能
一、for循環語句
1. for循環語法結構
(一)列表循環
列表for循環:用于將一組命令執行已知的次數
-
基本語法格式
舉例說明:
[root@localhost ~]# for var in {1..10};do echo $var;done [root@localhost ~]# for var in 1 2 3 4 5;do echo $var;done [root@localhost ~]# for var in `seq 10`;do echo $var;done [root@localhost ~]# for var in $(seq 10);do echo $var;done [root@localhost ~]# for var in {0..10..2};do echo $var;done [root@localhost ~]# for var in {2..10..2};do echo $var;done [root@localhost ~]# for var in {10..1};do echo $var;done [root@localhost ~]# for var in {10..1..-2};do echo $var;done [root@localhost ~]# for var in `seq 10 -2 1`;do echo $var;done ?(二)不帶列表循環
不帶列表的for循環執行時由用戶指定參數和參數的個數
-
基本語法格式
舉例說明:
#testfor.sh #!/bin/bash for var do echo $var done echo "They are $# parameters after the script" [root@localhost tmp]# ./testfor.sh 1 2 3 4 5 1 2 3 4 5 They are 5 parameters after the script [root@localhost tmp]# ./testfor.sh `seq 10` 1 2 3 4 5 6 7 8 9 10 They are 10 parameters after the script ?(三)類C風格的for循環
-
基本語法結構
2. 案例
(一)腳本計算1-100奇數和
① 思路
定義一個變量來保存奇數的和 ? sum=0
找出1-100的奇數,保存到另一個變量里 ?i=遍歷出來的奇數
從1-100中找出奇數后,再相加,然后將和賦值給變量 ?循環變量 ?for
遍歷完畢后,將sum的值打印出來
② 落地實現
#!/bin/env bash # 計算1-100的奇數和 # 定義變量來保存奇數和 sum=0方法1: #for循環遍歷1-100的奇數,并且相加,把結果重新賦值給sum for i in {1..100..2} dolet sum=$sum+$i done #打印所有奇數的和 echo "1-100的奇數和是:$sum" 方法1: #!/bin/bash sum=0 for i in {1..100..2} dosum=$[$i+$sum] done echo "1-100的奇數和為:$sum"方法2: #!/bin/bash sum=0 for ((i=1;i<=100;i+=2)) dolet sum=$i+$sum done echo "1-100的奇數和為:$sum"方法3: #!/bin/bash sum=0 for ((i=1;i<=100;i++)) doif [ $[$i%2] -ne 0 ];thenlet sum=$sum+$ifi或者test $[$i%2] -ne 0 && let sum=$sum+$i done echo "1-100的奇數和為:$sum"方法4: sum=0 for ((i=1;i<=100;i++)) doif [ $[$i%2] -eq 0 ];thencontinueelselet sum=$sum+$ifi或者用test $[$i%2] -eq 0 && continue || let sum=sum+$i 替換if...else done echo?"1-100的奇數和為:$sum" ?③ 循環控制語句
循環體: do....done之間的內容
-
continue:繼續;表示循環體內下面的代碼不執行,重新開始下一次循環
-
break:打斷;退出循環體,執行循環體后面的代碼
-
exit:表示直接跳出程序
(二)判斷所輸整數是否為質數
質數(素數):只能被1和它本身整除的數。2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
① 思路
讓用戶輸入一個數,保存到一個變量里
如果能被其他數整除就不是質數——>$num%$i是否等于0$i=2到$num-1
如果輸入的數是1或者2取模根據上面判斷又不符合,所以先排除1和2
測試序列從2開始,輸入的數是4——>得出結果$num不能和$i相等,并且$num不能小于$i
② 落地實現
#!/bin/bash read -p "請輸入一個正整數字:" number[ $number -eq 1 ] && echo "$number不是質數" && exit [ $number -eq 2 ] && echo "$number是質數" && exitfor i in `seq 2 $[$number-1]`do[ $[$number%$i] -eq 0 ] && echo "$number不是質數" && exitdone echo "$number是質數" && exit ?(三)批量創建用戶
需求:批量加5個新用戶,以u1到u5命名,并統一加一個新組,組名為class,統一改密碼為123
① 思路
添加用戶的命令 useradd
判斷class組是否存在 grep -w class /etc/group
根據題意,判斷該腳本循環5次來添加用戶給用戶設置密碼,應該放到循環體里面
② 落地實現
?
3. 練習
(一) 批量創建用戶
需求1:批量新建5個用戶stu1~stu5,要求這幾個用戶的家目錄都在/rhome.
#!/bin/env?bash #判斷/rhome是否存在?-f?判斷文件是否存在并且是一個普通文件 [ -f /rhome ] && mv /rhome /rhome.bak #/rhome文件不存在且不是一個文件不是一個目錄,則創建這個文件 #?-a?等價于 && test ! -f /rhome -a ! -d /rhome && mkdir /rhome 或者 [ -f /rhome ] && mv /rhome /rhome.bak || [ ! -d /rhome ] && mkdir /rhome #創建用戶,循環5次 for ((i=1;i<=5;i++)) do#-d?指定與用戶登錄時的主目錄useradd -d /rhome/stu$i stu$iecho 123|passwd --stdin stu$i done ?(二)局域網內腳本檢查主機網絡通訊
需求2:寫一個腳本,局域網內,把能ping通的IP和不能ping通的IP分類,并分別保存到兩個文本文件里。假定局域網的ip地址范圍為:10.1.1.1~10.1.1.10
#!/bin/bash #定義變量 ip=10.1.1 #循環去ping主機的IP for ((i=1;i<=10;i++)) doping -c1 $ip.$i &>/dev/nullif [ $? -eq 0 ];thenecho "$ip.$i is ok" >> /tmp/ip_up.txtelseecho "$ip.$i is down" >> /tmp/ip_down.txtfi或者[ $? -eq 0 ] && echo "$ip.$i is ok" >> /tmp/ip_up.txt || echo "$ip.$i is down" >> /tmp/ip_down.txt done[root@localhost tmp]# vim ping.sh [root@localhost tmp]# chmod +x ping.sh [root@localhost tmp]# time ./ping.shreal 1m40.068s user 0m0.022s sys 0m0.037s ?延伸擴展:shell腳本并發
并行執行:{程序}&?表示將程序放到后臺并行執行,如果需要等待程序執行完畢再進行下面內容,需要加wait
#!/bin/env?bash #定義變量 ip=10.1.1 #循環去ping主機的IP for ((i=1;i<=10;i++)) do {ping -c1 $ip.$i &>/dev/nullif [ $? -eq 0 ];thenecho "$ip.$i is ok" >> /tmp/ip_up.txtelseecho "$ip.$i is down" >> /tmp/ip_down.txtfi }& done wait echo "ip is okey" [root@localhost tmp]# time ./ping.sh ip is okeyreal 0m10.061s user 0m0.011s sys 0m0.039s ?并發執行與順序執行的速度顯而易見。
(三)判斷閏年
需求3:輸入一個年份,判斷是否是潤年(能被4整除但不能被100整除,或能被400整除的年份即為閏年)
#!/bin/env bash read -p "Please input year:(2020)" year if [ $[$year%4] -eq 0 && $[$year%100] -ne 0 ];thenecho "$year is leap year" elif [ $[$year%400] -eq 0 ];thenecho "$year is leap year" elseecho "$year is not leap year" fi ?4. 總結
-
FOR循環語法結構
-
FOR循環可以結合條件判斷和流程控制語句
-
do ......done ?循環體
-
循環體里可以是命令集合,再加上條件判斷以及流程控制
-
-
循環控制語句
-
continue ?繼續,跳過本次循環,繼續下一次循環
-
break ? ? ? 打斷,跳出循環,執行循環體外的代碼
-
exit ? ? ? ? ?退出,直接退出程序
-
二、while循環語句
特點:條件為真就進入循環;條件為假就退出循環
1. while循環語法結構
while 表達式docommand...donewhile [ 1 -eq 1 ] 或者 (( 1 > 2 ))docommandcommand...done ?循環打印1-5數字
FOR循環打印: for ((i=1;i<=5;i++)) doecho $i donewhile循環打印: i=1 while [ $i -le 5 ] # -le表示小于d等于 doecho $ilet i++ done ?2. 應用案例
(一) 腳本計算1-100偶數和
#!/bin/env bash sum=0 i=2 while?[ $i -le 100 ] dolet sum=$sum+$ilet?i+=2 done echo?"1-100以內的偶數之和為:$sum" ?(二)腳本同步系統時間
① 具體需求
寫一個腳本,30秒同步一次系統時間,時間同步服務器10.1.1.1
如果同步失敗,則進行郵件報警,每次失敗都報警
同步成功,也進行郵件通知,但是成功100次才通知一次
② 思路
每個30s同步一次時間,該腳本是一個死循環 (rdate命令用于顯示其他主機的日期與時間,rdate -s ntp_server 表示把遠程服務器ntp_server的時間同步到本地。)
同步失敗發送郵件 (mail -s "主題" 郵件地址)
同步成功100次發送郵件
③ 落地實現
#!/bin/env?bash count=0?#用于記錄發送成功的次數 ntp_server=10.1.1.1 while true dordate?-s?$ntp_server?&>/dev/nullif [ $? -eq 0 ];thenlet count++if [ $[$count%100] -eq 0 ];thenecho "system date successfull" | mail -s 'check system date' root@localhost && count=0fielseecho "system date failed" | mail -s 'check system date' root@localhost fi sleep 3 done ?三、until循環
特點:條件為假就進入循環;條件為真就退出循環
1. until語法結構
until expression [ 1 -eq 1 ] (( 1 >= 1 )) docommandcommand... done ?打印1-10數字
i=1 while?[?$i?-le?10 ] doecho $ilet i++ donei=1 until [ $i -gt 10 ] doecho $ilet i++ done ?2. 應用案例
① 具體需求
使用until語句批量創建10個用戶,要求stu1—stu5用戶的UID分別為1001—1005;
stu6~stu10用戶的家目錄分別在/rhome/stu6—/rhome/stu10
② 思路
?
對于stu1—stu5用戶的UID設置可用通過命令 useradd -u uid 進行設置;
stu6~stu10用戶的家目錄可以通過 useradd -d dir_name 進行設置
③ 落地實現
#!/bin/env bash i=1 until [ i -gt 10 ] doif?[?$i?-le?5?];thenuseradd?-u?$[1000+$i]?stu$i?&&?echo?"123"?|?passwd?--stdin?stu$ielse[!?-d /rhome ] && mkdir /rhomeuseradd -d /rhome/stu$i && echo "123" | passwd --stdin stu$ifi let i++ done ?四、家庭作業
判斷/tmp/run目錄是否存在,如果不存在就建立,如果存在就刪除目錄里所有文件
輸入一個路徑,判斷路徑是否存在,而且輸出是文件還是目錄,如果是鏈接文件,還得輸出是 ?有效的連接還是無效的連接
交互模式要求輸入一個ip,然后腳本判斷這個IP 對應的主機是否 能ping 通,輸出結果類似于:Server ?10.1.1.20 is Down! 最后要求把結果郵件到本地管理員root@localhost mail01@localhost
寫一個腳本/home/program,要求當給腳本輸入參數hello時,腳本返回world,給腳本輸入參數world時,腳本返回hello。而腳本沒有參數或者參數錯誤時,屏幕上輸出“usage:/home/program hello or world”
寫一個腳本自動搭建nfs服務
總結
以上是生活随笔為你收集整理的Linux从入门到精通系列之SHELL编程循环语句语法及实例详解(forwhileuntil)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MATLAB实战系列(二十二)-matl
- 下一篇: 深度学习核心技术精讲100篇(二十七)-