第五天03條件判斷與循環

 
 
   選擇執行
    選擇執行:注意:if語句可嵌套              
           
單分支                                                                         雙分支 :                                    
      if 判斷條件 ;then                                                         if 判斷條件 ; then
            條件為真的分支代碼                                                    條件為真的分支代碼
      fi                                                                                   else
                                                                                                  條件為真的分支代碼
                                                                                            fi
—————————————————————————————————————————————
多分支                                                                                                    條件判斷:case語句
       if    判斷條件1 ; then                                                                           case  變量引用  in
               條件為真的分支代碼                                                                     pattern1)
       elif  判斷條件2 ; then                                                                                           條件為真的分支代碼      
              條件為真的分支代碼                                                                                      ;;
       elif  判斷條件3 ; then; then                                                                 pattern2)
               條件為真的分支代碼                                                                                     條件為真的分支代碼      
            …                                                                                                                       ;;
       else                                                                                                         …..
               all-false                                                                                           *)
       fi                                                                                                                             條件為真的分支代碼 ,  默認分支
                                                                                                                                      ;;
                                                                                                                      esac
                                                                                                                                                                                                                                   
多分支(if),逐條件進行判斷,第一次遇為“真”條件時,                     條件判斷(case):
執行其分支,而后結束整個if語句                                                                       支持glob風格的通配符:     *  : 任意長度任意字符
                                                                                                                                                                         ?  : 任意單個字符
例子:  根據命令的退出狀態來執行命令                                                                                                           [ ]:指定范圍內的任意單個字符
if ping -c2 -w2 $1 &> /dev/null ;then                                                                                                        [^ ]:指定范圍外的任意單個字符
  echo "$1:is up"                                                                                                                                            a|b: a或b
elif grep "$1" ~/ipaddrs.txt &> /dev/null ;then
  echo "$1 :is non-existent"
else
  echo "$1 is unexpectedly down!"
  exit 1
fi
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/1.png

判斷正則
 if [[ $i  =~  ^S  ]] 判斷正則變量

—————————————————————————————————————————————————————————–

循環
循環執行,將某代碼段重復運行多次
重復運行多少次:  循環次數事先已知    循環次數事先未知    有進入條件和退出條件

for 變量名  in   列表  ;do                                                    列表生成方式:(1) 直接給出列表  
      循環體                                                                                                     (2) 整數列表:(a) {start..end}           touch {1..5}.txt
done                                                                                                                                     (b) $(seq start end )   seq 1 100
                                                                                                                      (3) 返回列表的命令: $(命令)    $(ls)
                                                                                                                      (4) 使用glob,如:ls*.sh
執行機制:                                                                                                    (5) 變量引用:$@, $*
依次將列表中的元素賦值給“變量名”;
每次賦值后即執行一次循環體; 直到列表中的元素耗盡,循環結束

while 條件; do
循環體
done
條件:循環控制條件;進入循環之前,先做一次判斷;每一次循環之后會再次做判斷;條件為“true”,則執行一次循環;直到條件測試狀態為“false”終止循環
因此:條件一般應該有循環控制變量;而此變量的值會在循環體不斷地被修正
進入條件:條件為true;      退出條件:條件為false

until循環
   until   條件    ; do
         循環體
     done
進入條件:條件 為false    退出條件:條件 為true

循環控制語句continue
用于循環體中,
continue [N]:提前結束第N層的本輪循環,而直接進入下一輪判斷;最內層為第1層
while condition1 ; do
cmd1

if  condtion2; then
   continue
fi
 cmdn
  …
done
continue命令與break命令類似,只有一點差別,它不會跳出所有循環,僅僅跳出當前循環。
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/2.png
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/3.png

循環控制語句break
break [N]:提前結束第N層循環,最內層為第1層
while 條件1 ; do
cmd

if  條件2; then
break
fi
cmdn

done
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/4.png
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/5.png

創建無限循環
while true; do                                               until false ; do
    循環體                                                               循環體
done                                                               done

特殊用法
while循環的特殊用法(遍歷文件的每一行):
   while read line; do
       循環體
   done < /PATH/FROM/SOMEFILE
依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將行賦值給變量line
練習
掃描/etc/passwd文件每一行,如發現GECOS字段為空,則填充用戶名和單位電話為62985600,并提示該用戶的GECOS信息修改成功。
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/6.png

特殊用法
雙小括號方法,即((…))格式,也可以用于算術運算
雙小括號方法也可以使bash Shell實現C語言風格的變量操作
#a=10      #((a++))
for循環的特殊格式:
    for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式))
       do
             循環體
       done
控制變量初始化:僅在運行到循環代碼段時執行一次
控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,而后再做條件判斷
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/7.png

select 循環與菜單
    select variable in list
    do
           循環體命令
    done
select 循環主要用于創建菜單,按數字順序排列的菜單項將顯示在標準錯誤上,并顯示PS3 提示符,等待用戶輸入
用戶輸入菜單列表中的某個數字,執行相應的命令
用戶輸入被保存在內置變量REPLY 中。

select 與case

select 是個無限循環,因此要記住用break 命令退出循環,或用exit 命令終止腳本。也可以按ctrl+c 退出循環。
select 經常和case 聯合使用
與for 循環類似,可以省略in list ,此時使用位置參量
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/8.png

select 與case
select 是個無限循環,因此要記住用break 命令退出循環,或用exit 命令終止腳本。也可以按ctrl+c 退出循環。
select 經常和case 聯合使用
與for 循環類似,可以省略in list ,此時使用位置參量

函數介紹
函數function是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程。
它與shell程序形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運行,而是shell程序的一部分。
函數和shell程序比較相似,區別在于:
Shell程序在子Shell中運行
而Shell函數在當前Shell中運行。因此在當前Shell中,函數可以對shell中變量進行修改

定義函數
函數由兩部分組成:函數名和函數體。
語法一:
function f_name{
    …函數體…
}
     語法二:
f_name() {
   …函數體…
}

函數使用
函數的定義和使用:
可在交互式環境下定義函數
可將函數放在腳本文件中作為它的一部分
可放在只包含函數的單獨文件中
   調用:函數只有被調用才會執行;
調用:給定函數名
函數名出現的地方,會被自動替換為函數代碼
   函數的生命周期:被調用時創建,返回時終止

函數返回值
函數有兩種返回值:
函數的執行結果返回值:
(1) 使用echo或printf命令進行輸出
(2) 函數體中調用命令的輸出結果
 函數的退出狀態碼:
(1) 默認取決于函數中執行的最后一條命令的退出狀態碼
(2) 自定義退出狀態碼,其格式為:
return 從函數中返回,用最后狀態命令決定返回值
return 0 無錯誤返回。
return 1-255 有錯誤返回

交互式環境下定義和使用函數
示例:
$dir() {
      > ls-l
> }
定義該函數后,若在$后面鍵入dir,其顯示結果同ls-l的作用相同。
$dir
  該dir函數將一直保留到用戶從系統退出,或執行了如下所示的unset命令:
$ unset    dir

在腳本中定義及使用函數
  函數在使用前必須定義,因此應將函數定義放在腳本開始部分,直至shell首次發現它后才能使用
 調用函數僅使用其函數名即可。
 示例:
$cat func1
#!/bin/bash
# func1
hello()
{
echo "Hello there today's date is `date +%F`"
}
echo "now going to the function hello"
hello
echo "back from the function"

使用函數文件
     可以將經常使用的函數存入函數文件,然后將函數文件載入shell。
     文件名可任意選取,但最好與相關任務有某種聯系。例如:functions.main
     一旦函數文件載入shell,就可以在命令行或腳本中調用函數??梢允褂胹et命令查看所有定義的函數,其輸出列表包括已經載入shell的所有函數。
    若要改動函數,首先用unset命令從shell中刪除函數。改動完畢后,再重新載入此文件。

創建函數文件
         函數文件示例:
$cat functions.main
#!/bin/bash
#functions.main
findit()
{
if [ $#  -lt  1 ] ; then
echo "Usage:find  it  file"
return 1
fi
find / -name $1 –print
}

載入函數
   函數文件已創建好后,要將它載入shell
  定位函數文件并載入shell的格式:
   .  filename 或  source filename
   注意:此即<點> <空格> <文件名>
   這里的文件名要帶正確路徑
   示例:上例中的函數,可使用如下命令:
   $ . functions.main
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/9.png

檢查載入函數
     使用set命令檢查函數是否已載入。set命令將在shell中顯示所有的載入函數。
      示例:
$set
findit=( )
{
if [ $# -lt1 ]; then
echo "usage :finditfile";
return 1
fi
find / -name $1 -print
}

執行shell函數
   要執行函數,簡單地鍵入函數名即可:
    示例:
$finditgroups
/usr/bin/groups
/usr/local/backups/groups.bak

刪除shell函數
   現在對函數做一些改動。首先刪除函數,使其對shell不可用。使用unset命令完成此功能.
   命令格式為:
   unset function_name
   實例:
$unset findit
再鍵入set命令,函數將不再顯示

函數參數
  函數可以接受參數:
傳遞參數給函數:調用函數時,在函數名后面以空白分隔給定參數列表即可;例如“testfuncarg1 arg2 …”
在函數體中當中,可使用$1, $2, …調用這些參數;還可以使用$@, $*, $#等特殊變量
file://C:\Users\tom\AppData\Local\Temp\ct_tmp/10.png

函數變量
  變量作用域:
環境變量:當前shell和子shell有效
本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此,本地變量的作用范圍是當前shell腳本程序文件,包括腳本中的函數。
局部變量:函數的生命周期;函數結束時變量被自動銷毀
   注意:如果函數中有局部變量,如果其名稱同本地變量,使用局部變量。
   在函數中定義局部變量的方法
local NAME=VALUE

函數遞歸實例
   函數遞歸:
函數直接或間接調用自身
注意遞歸層數
   遞歸實例:
階乘是基斯頓·卡曼于1808 年發明的運算符號,是數學術語
一個正整數的階乘(factorial)是所有小于及等于該數的正整數的積,并且有0的階乘為1。自然數n的階乘寫作n!。
n!=1×2×3×…×n。
階乘亦可以遞歸方式定義:0!=1,n!=(n-1)!×n。
n!=n(n-1)(n-2)…1
n(n-1)! = n(n-1)(n-2)!

函數遞歸示例
  示例:fact.sh
#!/bin/bash
#
function fact() {
if [ $1 -eq 0 -o $1 -eq1 ]; then
       echo 1
else
       echo $[$1*$(fact $[$1-1])]
fi
}
fact 5

定義數組
聲明數組:
declare -a ARRAY_NAME
declare -A ARRAY_NAME: 關聯數組
數組元素的賦值:
(1) 一次只賦值一個元素;
ARRAY_NAME[INDEX]=VALUE
weekdays[0]="Sunday"
weekdays[4]="Thursday"
(2) 一次賦值全部元素:
ARRAY_NAME=("VAL1" "VAL2" "VAL3" …)
(3) 只賦值特定元素:
ARRAY_NAME=([0]="VAL1" [3]="VAL2" …)
(4) 交互式數組值對賦值
read -a ARRAY

引用數組
  引用數組元素:${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下標為0的元素
  數組的長度(數組中元素的個數):
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
 示例:生成10個隨機數保存于數組中,并找出其最大值和最小值
#!/bin/bash
declare -a rand
declare -imax=0
for iin {0..9}; do
rand[$i]=$RANDOM
echo ${rand[$i]}
[ ${rand[$i]} -gt$max ] && max=${rand[$i]}
done
echo "Max: $max

數組數據處理
   引用數組中的元素:
所有元素:${ARRAY[@]}, ${ARRAY[*]}
數組切片:${ARRAY[@]:offset:number}
offset: 要跳過的元素個數
number: 要取出的元素個數
取偏移量之后的所有元素${ARRAY[@]:offset}
  向數組中追加元素:
ARRAY[${#ARRAY[*]}]
  刪除數組中的某元素:導致稀疏格式
unset ARRAY[INDEX]
  關聯數組:
declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]=('val1' [idx_name2]='val2‘…)

字符串處理
bash的字符串處理工具:
字符串切片:
${#var}:返回字符串變量var的長度
${var:offset}:返回字符串變量var中從第offset個字符后(不包括第offset個字符)的字符開始,到最后的部分,offset的取值在0 到${#var}-1 之間
${var:offset:number}:返回字符串變量var中從第offset個字符后(不包括第offset個字符)的字符開始,長度為number的部分
${var: -lengh}:取字符串的最右側幾個字符:
注意:冒號后必須有一空白字符

字符串處理
基于模式取子串:
${var#*word}:其中word可以是指定的任意字符
功能:自左而右,查找var變量所存儲的字符串中,第一次出現的word, 刪除字符串開頭至第一次出現word字符之間的所有字符
${var##*word}:同上,不同的是,刪除的是字符串開頭至最后一次由word指定的字符之間的所有內容
file="/var/log/messages"
${file##*/}: messages

20160816作業

一、用until實現下列作業

1、每隔3秒鐘到系統上獲取已經登錄的用戶的信息;如果發現用戶hacker登錄,則將登錄時間和主機記錄于日志/var/log/login.log,并提示該用戶退出系統。

loginNum=0  #定義入侵狀態

until false

do

sleep 3

#假設除管理終端pts0外,其他用戶為非法,如xiong

loginNum=`w | grep "pts" | wc -l`

 if [ $loginNum -gt 1 ];then

    #定義hacker用戶

    hacker=`w | sed '1,2d' |grep -v 'root' | awk '{print $1}'`  

    #定義黑客終端

    hcpts=/dev/`w | sed '1,2d' |grep -v 'root' | awk '{print $2}' `

    #記錄入侵日志

    w | grep "pts" | awk '{print "user:"$1"  login time: "$4}' >> /var/log/login.log

    #給黑客發信

    echo "Unauthorized users, you have been recording, please exit the system." | write $hacker $gcots

 fi

done

圖片1.png

2、隨機生成10以內的數字,實現猜字游戲,提示比較大或小,相等則退出

#!/bin/bash

#author:maoxiong QQ:111111111

#verson:1.0  date:2016-08  #illustrate:

randomNum=0

myNum=1

until [ $randomNum -eq $myNum ]

do

  randomNum=$(($RANDOM%10))

  read -p "please input a num: " var

  myNum=$var

  echo "randomNum:$randomNum  , inputNum: $myNum"

  if [ $myNum -lt $randomNum ];then

      echo "randomNum is big,l lose"

  elif [ $myNum -gt $randomNum ];then

      echo "inputNum is big,l win"

  else

      echo "randomNum=inputNum,exit"

  fi

done

圖片2.png

3、編寫腳本,求100以內所有正整數之和

#!/bin/bash

#author:maoxiong QQ:111111111

#verson:1.0  date:2016-08  #illustrate:

sum=0

count=1

until [ $count -gt 100 ];do

   let  sum+=count

   ((count++))

done

echo "1+…+100= $sum"

圖片3.png

4、編寫腳本,通過ping命令探測172.16.250.1-254范圍內的所有主機的在線狀態,統計在線主機和離線主機各多少。

#!/bin/bash

#author:maoxiong QQ:111111111

#verson:1.0  date:2016-08

#illustrate:

aliveNum=0   #在線主機

deathNum=0   #不在主機

hostNum=1    #主機總數

#截取主機網絡段

read -p "please input a network:" net

aliveNet=`echo $net | grep -E -o "(\<([0-9]|[1-9][0-9]|1[0-9](2)|2[0-4][0-9]|25[0-5]\>)\.){3}"`

     

until [ $hostNum -eq 5 ] ;do

    ip=$aliveNet$hostNum

    ping -c 2 -w 2 $ip &> /dev/null && echo "$ip is up" || echo "$ip is down"

    ping -c 2 -w 2 $ip &> /dev/null && let aliveNum+=1 || let deathNum+=1

    let hostNum+=1

done

echo "ip is up ,num: $aliveNum ,ip is down ,num: $deathNum"

圖片4.png

5、編寫腳本,打印九九乘法表

#!/bin/bash

#author:maoxiong QQ:111111111

#verson:1.0  date:2016-08

#illustrate:

u1num1=1

u2num2=1

until [ $u1num1 -gt 9 ];do

   until [ $u2num2 -gt $u1num1 ];do

        echo -en "$u2num2*$u1num1=$(($u2num2*$u1num1))\t"

   let u2num2+=1

   done

   echo

   let u1num1+=1

   let u2num2=1

done

圖片5.png

6、編寫腳本,利用變量RANDOM生成10個隨機數字,輸出這個10數字,并顯示其中的最大者和最小者

#!/bin/bash

#author:maoxiong QQ:111111111

#verson:1.0  date:2016-08

#illustrate:

count=1   #循環次數

maxNum=0  #最大數

minNum=0  #最小數

until [ $count -gt 10 ];do

    randomNum=$(($RANDOM+10000))$(($RANDOM+10000))  #生成隨機數

    [ $count -eq 1 ] && let minNum=randomNum        #將第一個隨機數賦值為最小

    if [ $randomNum -lt $minNum ];then

         let minNum=randomNum

         echo $randomNum

    elif [ $randomNum -ge $maxNum ];then

         let maxNum=randomNum

         echo $randomNum

    else

         echo $randomNum

    fi  

    let count+=1

done

echo "maxNum=$maxNum  ,  minNum=$minNum"

圖片6.png

7、編寫腳本,實現打印國際象棋棋盤

#!/bin/bash

#author:maoxiong QQ:111111111

#verson:1.0  date:2016-08

#illustrate:

count1=1

count2=1

until [ $count1 -gt 8 ] ;do

   until [ $count2 -gt 8 ];do

         # $count1%2 判斷基數行還是偶數行      $count2/2 判斷是每行打印空格顏色順序

         if [ $(($count1%2)) -eq 1 ];then

                   [ $(($count2%2)) -eq 1 ] && echo -e -n "\033[47;30m  \033[0m" || echo -e -n "\033[46;30m  \033[0m"

         else

                  [ $(($count2%2)) -eq 1 ] && echo -e -n "\033[46;30m  \033[0m" || echo -e -n "\033[47;30m  \033[0m"

         fi  

      let count2+=1

   done

   echo ""

   let count1+=1

   let count2=1

done

圖片7.png

、打印等腰三角形

lineNum=1   #行號

u2num=1     #*號初始控制數

u1num=0     #空格初始控制數

read -p "please input a number:" var

until [ $lineNum -gt $var ] ;do

    let spaceNum=$var-lineNum  #需要打印空格參數

    until [ $u1num -eq $spaceNum ];do

       echo -en ' '

       let u1num+=1

    done

    let num2=2*lineNum-1      #每行*要打印數

    until [ $u2num -gt $num2 ];do    

       echo -en "*"

       let u2num+=1

    done

 echo ""

 let u2num=1

 let u1num=0    

 let lineNum+=1  

done 

圖片8.png

原創文章,作者:maoxiong,如若轉載,請注明出處:http://www.www58058.com/37168

(0)
maoxiongmaoxiong
上一篇 2016-08-18
下一篇 2016-08-18

相關推薦

  • python基礎 習題總結

    pyenv 編程題目總結(99乘法表 打印菱形與閃電 斐波那契數列 素數 猴子吃桃) 原反補碼與異或運算 list列表

    Linux干貨 2018-03-25
  • 三大家族輕松管理CentOS 7網絡屬性配置

    一、簡單介紹        在CentOS 7中對網絡管理還是有不少變化的,例如管理服務的命令變為systemctl,許多命令可以更改后直接生效,還有許多獨有的工具,本文以CentOS 6與CentOS 7對比進行講解,下面現總體介紹一下網絡屬性配置工具。    &nb…

    Linux干貨 2016-04-25
  • 利用varnish構建httpd緩存服務器

    varnish如何存儲緩存對象:     file: 單個文件;不支持持久機制;     malloc: 緩存在內存中;     persistent:基于文件的持久存儲;(此方式不建議使用) vcl:配置緩存系統的緩存機制;【線程中緩存功…

    Linux干貨 2016-06-20
  • C++的std::string的“讀時也拷貝”技術!

    C++的std::string的讀時也拷貝技術! 嘿嘿,你沒有看錯,我也沒有寫錯,是讀時也拷貝技術。什么?我的錯,你之前聽說寫過時才拷貝,嗯,不錯的確有這門技術,英文是Copy On Write,簡寫就是COW,非?!!?!那么我們就來看看這個’?!夹g的效果吧。 我們先編寫一段程序 #include <string> #include…

    Linux干貨 2015-04-03
  • 基于NFS服務的mariadb數據庫實現

    實驗要求:     (1) nfs server導出/data/目錄;     (2) nfs client掛載/data/至本地的/mydata目錄;本地的mysqld或mariadb服務的數據目錄設置為/mydata, 要求服務能正常啟動,且可正常 存儲數據;   (3)用另一臺主機,…

    2017-06-11
  • 程序員小抄大全

    你是否會經常忘記一些CSS中的函數名或是一些屬性名,那個時候,你一定覺得,如果手邊有一個“小抄”(Cheat Sheet)就好了。當然,這個“小抄”不是給你作弊用的,這個“小紙條”就是可以讓你馬上知道那個你最想知道的東西。這個“小抄”上也不需要有所有的東西,就需要那些經常用的就行了。現在,網上有很多這樣的“小抄”,它們可能是PDF格式的,可能是PNG格式的,…

    Linux干貨 2015-04-03

評論列表(1條)

  • 馬哥教育
    馬哥教育 2016-08-19 09:37

    前面整體看起來太散亂了,作業完成的還不錯,排版可以更寫的好的人學習一下,爭取寫出優秀的博文來。

欧美性久久久久