標籤:矩形 exp 指定 nohup 多少 exit sed 取出 row
這篇文章主要介紹shell編程的執行個體
一、邏輯判斷之if語句1.判斷年齡?
[[email protected] 9_1 ]#cat iftest.sh #!/bin/bashread -p "Please input your age:" age ## 判斷使用者輸入的必須是數字if [[ "$age" =~ ^[0-9]+$ ]];then trueelse echo "Please input digit" exit 10fi## 判斷使用者的年齡,並輸出相應的資訊if [ "$age" -ge 0 -a $age -le 18 ];then echo "good good study,day day up"elif [ "$age" -gt 18 -a $age -le 60 ];then ## 由於前面已經判斷為數字,並且為正整數,所以的 "$age" -gt 18 可以省略; echo "work hard"elif [ "$age" -gt 60 -a $age -le 120 ];then ## 同理,這裡的"$age" -gt 60也可以省略,最佳化 echo "enjoy your life"else echo "you don not come from the earch"fi
2.如何判斷yes或no?
思路1:
1.使用者輸入的所有選擇:y|yes|Y|YES,同n|no|N|NO
2.統一判斷為大寫或者小寫:tr進行轉換
3.使用兩種選擇判斷:2:使用正則匹配y|yes;n|no或者大寫
#!/bin/bashread -p "Input yes or no:" answerans=`echo "$answer"|tr ‘A-Z‘ ‘a-z‘`if [ "$ans" = "yes" -o "$ans" = "y" ];then echo "YES"elif [ "$ans" = "no" -o "$ans" = "n" ];then echo "NO"else echo "Please input yes or no"fi
思路2:使用正則進行判斷
#!/bin/bashread -p "Input yes or no:" answerif [[ "$answer" =~ ^[Yy]([Ee][Ss])?$ ]];then echo YESelif [[ "$answer" =~ ^[Nn][Oo]?$ ]];then echo "NO"else echo "Please input yes or no"fi
4.判斷是否富有或帥氣?
[[email protected] 9_1 ]#vim yesorno2.sh#!/bin/bashread -p "Are you rich? yes or no: " answerif [[ "$answer" =~ ^[Yy]([Ee][Ss])?$ ]];then echo OKelif [[ "$answer" =~ ^[Nn][Oo]?$ ]];then read -p "Are you handsome? yes or no: " answer if [[ "$answer" =~ ^[Yy]([Ee][Ss])?$ ]];then echo Ok exit elif [[ "$answer" =~ ^[Nn][Oo]?$ ]];then echo "work hard" else echo "Please input yes or no" fielse echo "Please input yes or no"fi
二、邏輯判斷之case語句1.判斷數字
[[email protected] 9_1 ]#vim casetest.sh#!/bin/bashread -p "Please input a digit: " numcase $num in1|2|3) echo 1,2,3 ;;4|5|6) echo 4,5,6 ;;7|8|9) echo 7,8,9 ;;*) echo other digit ;;esac
2.判斷yes|no
#!/bin/bashread -p "Please input yes or no: " anscase $ans in[Yy]|[Yy][Ee][Ss]) echo YES ;;[Nn]|[Nn][Oo]) echo NO ;;*) echo input false ;;esac
3.列印菜單:
[[email protected] ~ ]#cat menu.sh #!/bin/bashcat <<EOF1:lamian2:huimian3:daoxiaomian4:junbing5:mifanEOFread -p "Please choose the number: " numcase $num in 1) echo "lamian price is 15" ;;2) echo "huimian price is 18" ;;3) echo "daoxiaomian price is 13" ;;4) echo "junbing price is 10" ;;5) echo "mifan price is 2" ;;*) echo "INPUT false"esac效果:[[email protected] ~ ]#sh menu.sh 1:lamian2:huimian3:daoxiaomian4:junbing5:mifanPlease choose the number: 5mifan price is 2
三、迴圈之for迴圈
help for————兩種文法
文法1:
for NAME [in WORDS ... ] ; do COMMANDS; done
文法2:
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
[[email protected] 9_2 ]#for num in 1 2 3 4 5;do echo "num=$num"; donenum=1num=2num=3num=4num=5
1.不斷追加求和
[[email protected] 9_2 ]#sum=0; for num in 1 2 3 4 5; do sum=$[sum+num];done ;echo sum=$sumsum=15
2.求1+2+3+..+100的和 (面試題)
方法1: {1..100}產生序列[[email protected] 9_2 ]#sum=0; for num in {1..100}; do sum=$[sum+num];done ;echo sum=$sumsum=5050## 用於計算的方式有$[] 和$(())以及let等等。方法2:seq 100產生序列[[email protected] 9_2 ]#sum=0; for num in `seq 100`; do sum=$[sum+num];done ;echo sum=$sumsum=5050
2.1 求1+2+3+..+100以內所有奇數的和|所有偶數的和?
奇數之和:
[[email protected] ~ ]#sum=0; for num in {1..100..2}; do sum=$[sum+num];done ;echo sum=$sumsum=2500[[email protected] ~ ]#sum=0; for num in `seq 1 2 100`; do sum=$[sum+num];done ;echo sum=$sumsum=2500
偶數之和:
[[email protected] ~ ]#sum=0; for num in {2..100..2}; do sum=$[sum+num];done ;echo sum=$sumsum=2550[[email protected] ~ ]#sum=0; for num in `seq 2 2 100`; do sum=$[sum+num];done ;echo sum=$sumsum=2550
2.2 列印奇數和偶數的幾種方法?
[[email protected] 9_2 ]#seq 1 2 10————列印奇數13579[[email protected] 9_2 ]#seq 2 2 10————列印偶數246810[[email protected] 9_2 ]#seq 1 10 |sed -n "1~2p" ——————sed列印奇數13579[[email protected] 9_2 ]#seq 1 10 |sed -n "2~2p"————————sed列印偶數246810[[email protected] ~ ]#echo {1..10..2} ————————————————{}也可以實現輸出奇數1 3 5 7 9[[email protected] ~ ]#echo {2..10..2} ————————————————{}列印偶數2 4 6 8 10
3.練習:如何?批量執行一個目錄下的所有指令碼?————(前提:所有檔案都擁有x許可權,並且是非互動)
[[email protected] 9_2 ]#lscase_yesorno.sh test.sh[[email protected] 9_2 ]#[[email protected] 9_2 ]#for filename in *.sh;do ./$filename;donePlease input yes or no: yesYEShello,world
4.練習:大量建立user1..10的使用者,並設定密碼為magedu,設定首次登入更改密碼?
[[email protected] 9_2 ]#vim createuser_n.sh #!/bin/bashfor num in {1..10};do useradd user${num} echo "magedu" |passwd --stdin user${num} &> /dev/null passwd -e user${num} &> /dev/nulldone
5.練習:編寫一個×××掃描器,實現掃描一個網段(1-254)中那些主機是開機的?
## 預設是順序執行,ping完一個ip後再ping下一個,那麼可不可以並存執行?[[email protected] 9_2 ]#cat scanip.sh #!/bin/bash## 每次執行前清空檔案> /data/iplist.log net=172.20.129for i in {1..254};do## 添加{}實現並存執行 { if ping -c1 -W1 $net.$i &> /dev/null ;then echo $net.$i is up echo $net.$i >> /data/iplist.log ## 注意這裡是追加,所以在指令碼開始清空檔案 else echo $net.$i is down fi } & ## 前後對應,並放入後台執行donewait ## 由於需要手動按enter退出,所以添加wait命令自動結束最佳化版:互動式輸入[[email protected] 9_2 ]#vim scanip.sh #!/bin/bash> /data/iplist.log## 互動式輸入read -p "Please input the network:(eg:192.168.0.0):" net ## 截取前三段,否則出現1.1.1.0.249情況net=`echo $net|cut -d. -f1-3` for i in {1..254};do { if ping -c1 -W1 $net.$i &> /dev/null ;then echo $net.$i is up echo $net.$i >> /data/iplist.log else echo $net.$i is down fi } &donewait
6.練習:寫一個計算網路ID的netid.sh,ip地址和子網路遮罩做與運算,如下所示:
[[email protected] 9_2 ]#echo $[193&240]192[[email protected] 9_2 ]#cat netid.sh #!/bin/bashread -p "input a ip: " ip read -p "input a netmask: " netmask ## 每次cut取一個欄位,然後迴圈4次 for i in {1..4};do net=`echo $ip |cut -d. -f$i` mask=`echo $netmask |cut -d. -f$i` if [ $i -eq 1 ];then ## 先一個欄位與另外一個欄位相與,最後再進行組合 netid=$[net&mask] else netid=$netid.$[net&mask] fidoneecho netid=$netid最佳化版:[[email protected] 9_2 ]#cat netid.sh #!/bin/bashread -p "input a ip: " ipread -p "input a netmask: " netmaskfor i in {1..4};do net=`echo $ip |cut -d. -f$i` mask=`echo $netmask |cut -d. -f$i` subnetid=$[net&mask] if [ $i -eq 1 ];then netid=$subnetid else netid=$netid.$subnetid fidoneecho netid=$netid其他參考:[[email protected] 9_2 ]#cat netid1.sh #!/bin/bashread -p "input a ip: " ipread -p "input a netmask: " netmaskfor (( i = 1; i < 5; i++ ));do ip1=`echo $ip |cut -d. -f$i` netmask1=`echo $netmask |cut -d. -f$i` echo -n $[$ip1&$netmask1] ## 用-n實現不換行追加 if [ $i -eq 4 ];then ## 每次輸出一個網路id欄位後並輸出一個點,然後不斷追加 echo "" else echo -n "." fidone[[email protected] 9_2 ]#
7.練習:通過互動方式輸入行數和列數,列印出矩形?
[[email protected] 9_2 ]#cat rectangle.sh #!/bin/bashread -p "input line number: " xread -p "input colume number: " yfor row in `seq $x`;do ## 指定行數列印多行 for col in `seq $y`;do ## 通過指定列數列印一行 echo -e "*\c" done echo ## 每一行列印完後換行 done最佳化版:添加顏色顯示,並閃爍[[email protected] 9_2 ]#cat rectangle.sh #!/bin/bashread -p "input line number: " xread -p "input colume number: " yfor row in `seq $x`;do ## 指定行數列印多行 for col in `seq $y`;do ## 通過指定列數列印一行 color=$[RANDOM%7+31] ## RANDOM%7表示0-6,+31即31-37 echo -e "\033[1;5;${color}m*\033[0m\c" ## 1高亮顯示,5閃爍,\c換到行尾表示不換行 done echo ## 每一行列印完後換行 done[[email protected] 9_2 ]#
8.練習:列印等腰三角形
利用for的第二種文法實現[[email protected] 9_4 ]#cat fortriangle.sh#!/bin/bashread -p "Please input a line number: " linefor ((i=1;i<=line;i++));do for ((j=1;j<=$[line-i];j++));do echo -n " " done for ((k=1;k<=$[2*i-1];k++));do echo -n "*" done echo done
9.列印九九乘法表
方法1:
[[email protected] 9_4 ]#vim multi.sh#!/bin/bashfor i in {1..9};do ## 外層迴圈決定了打幾行,i相當於行號 for j in `seq $i`;do ## j表示其中的一行迴圈多少遍? echo -e "$j*$i=$(($j*$i))\t\c" ## 計算$j*$i的結果,並以tab分隔,不換行; done echo ## echo的位置表示列印一行後進行換行;done[[email protected] 9_4 ]#sh multi.sh 1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
思路:找規律,第一個數字是列編號 第二個數字是行號;
先列印一行 ,然後迴圈列印多行————————列印一行的時候,需要計算迴圈多少遍?——————最終發現由行號決定迴圈幾遍
方法2:C語言風格
[[email protected] 9_4 ]#cat for_mult.sh #!/bin/bashfor ((i=1;i<=9;i++));do for ((j=1;j<=i;j++));do echo -e "$j*$i=$[j*i]\t\c" done echo done
10.在/testdir目錄下建立10個html檔案,檔案名稱格式為數字N(從1到10)加隨機8個字母,如:1AbCdeFgH.html
[[email protected] 9_4 ]#vim create.sh #!/bin/bashfor i in {1..10};do touch $i`tr -dc "0-9a-zA-Z" < /dev/urandom|head -c8`done
四、迴圈之while迴圈1.練習:計算1+2+3+..+100的和
[[email protected] 9_4 ]#vim while.sh#!/bin/bashsum=0i=1while [ $i -le 100 ];do let sum+=i let i++doneecho sum=$sum "while.sh" [New] 8L, 86C written [[email protected] 9_4 ]#sh while.sh sum=5050
2.練習:九九乘法表
9_4 ]#vim whilemult.sh#!/bin/bashi=1while [ $i -le 9 ];do j=1 while [ $j -le $i ];do echo -e "$j*$i=$[$j*$i]\t\c" let j++ done echo let i++done[[email protected] 9_4 ]#sh whilemult.sh 1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=
3. 練習:列印等腰三角形
[email protected] 9_4 ]#cat while_triangle.sh #!/bin/bashread -p "Please input a line number: " linei=1 ## 列印多行while [ "$i" -le "$line" ];do ## print space ## 列印空格 j=1 while [ "$j" -le $[line-i] ];do echo -n " " ##或者使用 echo -e " \c" let j++ done ## print * ## 列印*的個數 k=1 while [ "$k" -le $[2*i-1] ];do echo -n "*" let k++ done let i++ echo done[[email protected] 9_4 ]#sh while_triangle.sh Please input a line number: 10 * *** ***** ******* ********* *********** ************* *************** ************************************
思路:先打出空格——————再列印*的個數
定義總行數:line
當前行:i
當前列:j
中間 所在列=總行數line
當前行從開頭到中間 的個數=i
space=line-i
當前行 的個數=2i-1
4.練習:監控httpd服務的狀態?
#!/bin/bashSLEEPTIME=10while : ;do ## :和true都表示為真 if killall -0 httpd &> /dev/null ;then ## kill -0 表示監控進程是否在運行 true else service httpd restart echo "At `date +‘%F %T‘` httpd restart" >> /var/log/checkhttpd.log fi sleep $SLEEPTIME ## 等待時間done##建議使用nohup script & 放入後台執行,終端的退出將不影響執行。
5.練習:編寫指令碼,利用變數RANDOM產生10個隨機數字,輸出這個10數字,並顯示其中的最大值和最小值
[[email protected] 9_4 ]#cat formaxmin.sh #!/bin/bashecho -e "random list:\c" for ((i=0;i<10;i++));do rand=$RANDOM echo -e " $rand\c" if [ $i -eq 0 ];then ## 第一次的隨機數字沒有可比的數字,所以既是最大值又是最小值; max=$rand min=$rand fi if [ $max -lt $rand ];then ## 如果隨機數大於最大值,則rand替換為最大值; max=$rand elif [ $min -gt $rand ];then ## 否則為假,即隨機數<max,並且<min,則替換為最小值。 min=$rand else true ## 如果是其他情況,則預設 fidoneechoecho max is $maxecho min is $min效果:[[email protected] 9_4 ]#sh formaxmin.sh random list: 18428 5303 6933 16210 2577 4107 23750 16836 3435 14399max is 23750min is 2577
五、迴圈之until迴圈
注意:為真,退出
為假,則執行迴圈語句
1.練習:查看系統登入使用者,如果有hacker這個登入使用者,則踢出去?
[[email protected] 9_4 ]#cat untiltest.sh #!/bin/bashuntil who|grep -q "^hacker\>";do sleep 3done ## 如果有hacker使用者在登入,則退出指令碼,並執行下面的pkill語句。pkill -9 -U hacker ## 注意 pkill -9 可以殺死使用者所有的進程。## 最佳化版:不退出指令碼,進入死迴圈,hacker一旦登入,則直接踢出去[[email protected] 9_4 ]#cat untiltest.sh #!/bin/bash until false; do ## 為假則進入死迴圈 who|grep -q "^hacker\>" && pkill -9 -U hacker sleep 3done
其他小練習1.練習:隨機產生10以內的數字,實現猜字遊戲,提示比較大或小,相等則退出
#!/bin/bashrand=$[RANDOM%11] ## 產生0-10的隨機數字while read -p "input a number: " num;do if [[ ! $num =~ ^[0-9]+$ ]];then ## 由於直接比較,不是>數位話會報錯,所以進行判斷; echo "Please input a digit" continue ## 結束本次迴圈 elif [ $num -gt $rand ];then echo $num is greater elif [ $num -lt $rand ];then echo $num is little else echo "guess OK" break ## 退出整個迴圈 fidone
2.練習:逐行讀取df的資訊,然後判斷分區的利用率是否大於8,大於則進行提示
方法1:
[[email protected] 9_4 ]#cat diskcheck.sh #!/bin/bashdf |sed -n "/sd/p"|while read line;do name=`echo $line |tr -s " " %|cut -d% -f1` ## 通過echo $line對讀取到的每一行進行處理 used=`echo $line |tr -s " " %|cut -d% -f5` if [ $used -gt 8 ];then echo "$name will be full;$used %" fidone[[email protected] 9_4 ]#sh diskcheck.sh/dev/sda2 will be full;9 %/dev/sda1 will be full;16 %
方法2:
#!/bin/bashdf |while read line;do if [[ "$line" =~ /dev/sd.* ]];then used=`echo $line|tr -s " " %|cut -d% -f5` if [ $used -gt 8 ];then echo "$line" |tr -s " " :|cut -d: -f1,5 fi fidone[[email protected] 9_4 ]#sh diskcheck1.sh /dev/sda2:9%/dev/sda1:16%
3.練習:掃描/etc/passwd檔案每一行,如發現GECOS欄位為空白,則填充使用者名稱和單位電話為62985600,並提示該使用者的GECOS資訊修改成功?
[[email protected] 9_4 ]#cat user.sh #!/bin/bashwhile read line ;do GECOS=`echo $line|cut -d: -f5` USER=`echo $line|cut -d: -f1` [ -z "$GECOS" ] && chfn -f $USER -p 2985600 $USER &> /dev/null;done < /etc/passwd
4.練習: ss -nt查看訪問串連的ip,如果達到兩個,就設定防火牆策略拒絕串連。
[[email protected] 9_4 ]#vim test.sh #!/bin/bashss -nt|sed -nr ‘/ESTAB/s/.* (.*):.*/\1/p‘|sort|uniq -c|while read line;do ## 取出ip並統計次數,然後逐行讀取;IP=`echo $line|cut -d" " -f2`num=`echo $line|cut -d" " -f1` if [ "$num" -ge 2 ];then iptables -A INPUT -s $IP -j REJECT ## 如果串連數>2,則使用防火牆策略阻止串連 else true fidone
5.select菜單
文法:select: select NAME [in WORDS ... ;] do COMMANDS; done
[[email protected] ~ ]#cat select.sh #!/bin/bashPS3="please choose a digit: " ## PS3專門用來提供輸入select MENU in jiaozi lamian mifan daoxiaomian quit;do ## in後面的參數預設按照序號1 2 3 4等一一對應; case $MENU in jiaozi) echo "Your choose is $REPLY" ## 變數REPLY專門用於儲存使用者輸入的結果 echo "$MENU price is 20" ;; lamian) echo "Your choose is $REPLY" echo "$MENU price is 15" ;; mifan) echo "Your choose is $REPLY" echo "$MENU price is 18" ;; daoxiaomian) echo "Your choose is $REPLY" echo "$MENU price is 12" ;; quit) echo "Your choose is $REPLY" break ;; *) echo "Your choose is $REPLY" echo "choose again" ;; esacdone效果:[[email protected] ~ ]#sh select.sh 1) jiaozi2) lamian3) mifan4) daoxiaomian5) quitplease choose a digit: 1Your choose is 1jiaozi price is 20please choose a digit: 2Your choose is 2lamian price is 15please choose a digit: 5Your choose is 5
shell指令碼練習