shell編程企業級實戰(2)


Vim配置文件.vimrc

vim配置文件

if 條件語句

if是最常見的條件判斷語句

 

 

例1:如果不存在/backup目錄就創建。
[root@web-01 /server/tools]# vim 07-01.sh
#!/bin/bas
path=/backup
[ -d $path ] || mkdir $path -p
# 相當於
# :冒號表示什么也不干
if [ -d $path ]
then
        :
else
        mkdir $path -p
fi
# 或者
[ !-d $path ] && mkdir /backdir -p
# 相當於
if [ !-d $path ]
then
        mkdir /backdir -p
if
"07-01.sh" 18L, 248C writte
vim命令:替換:%s#/backup#$path#g
例2:開發Shell腳本判斷系統剩余內存的大小,如果低於100MB就提示內存不足,否則提示內存充足。 考查if雙分支: 分析:
1)提取系統內存。 2)if判斷, [root@web01 07]# cat 07_02.sh #!/bin/bash ############################################################## # File Name: 07_02.sh # Version: V1.0 # Author: pizza # Created Time : 2018-06-06 22:58:54 # Description: ############################################################## mem=`free -m|awk 'NR==3{print $NF}'` if [ $mem -lt 1000 ] then echo "內存嚴重不足。" else echo "內存還夠" fi

在第一章的中添加了內存不足發郵件的例子
例3:分別使用變量定義、read讀入及腳本傳參方式實現比較2個整數的大小。 1)變量定義: a=6 b=2 2)read讀入: read -p "請輸入兩個數字:" a b 3)傳參: 分析: 大於 等於 小於 #!/bin/bash
##############################################################
# File Name: 07-03.sh
# Version: V1.0
# Author: pizza
# Created Time : 2019-03-28 21:20:46
# Description:
##############################################################
# 第一種,傳參
a=6
b=7
# 第二種,read
read -p "請輸入兩個數字" a b
# 第三種,參數
$a=$1
$b=$2
# 判斷輸入
# 1、判斷數字是不是夠,判斷b是不是空,或者使用$#
# 2、判斷是不是整數,利用expr
# 3、

if [ $a -gt $b ]
then
    echo "$a>$b"
elif [ $a -lt $b ]
then
    echo "$a<$b"
else
    echo "$a=$b"
fi

例4:打印一個菜單如下,當用戶選擇對應的數字時,就執行對應項的應用。
1.install lamp 2.install lnmp 3.exit 第一章已講解: bash內置核心命令read的企業級應用實踐 read企業應用 [root@web01 scripts]# cat select1.sh #!/bin/bash cat <<EOF 1.install lamp 2.install lnmp 3.exit EOF read -p "請選擇一個序號(必須是數字):" num #1.判斷是否為整數 expr 2 + $num &>/dev/null if [ $? -ne 0 ] then echo "Usage:$0 {1|2|3}" exit 1 fi #2.判斷執行處理 if [ $num -eq 1 ] then echo "install lamp..." elif [ $num -eq 2 ] then echo "install lnmp..." elif [ $num -eq 3 ] then echo "bye." exit else echo "Usage:$0 {1|2|3}" exit 1 fi

 

Shell函數的知識與實踐

函數的作用就是將程序里多次被調用的相同代碼組合起來,並為其取個名字。其他所有想重復調用這部分代碼的復方都只需要調用這個這個名字就可以了。當需要修稿這部分重復代碼的時候,也只需要改變函數內的一份代碼即可實現所有的修改,也可以把函數獨立寫到文件里面,當需要調用的時候,再加載進來。

 

函數的語法體

 

 

oldboy() {
    echo "I am oldboy."
}
function oldgirl {
    echo "I am oldgirl."
}
test() {
    echo "Hello world."
}
oldboy
oldgirl

[root@web-01 ~]# sh test_hanshu.sh
I am oldboy.
I am oldgirl.
Hello world.
[root@web-01 ~]#

 

向函數傳參

帶參數的函數編寫執行
oldboy() {
    echo "I am $1."
}
oldboy oldboy
將函數傳參轉為腳本傳參
oldboy() {
    echo "I am $1."
}
oldboy $1

函數和執行函數分離
./etc/init.d/function
pizza $1

 

Shell函數的執行注意事項

 

企業案例:通過腳本傳參的方式,檢查Web 網站URL是否正常。

wget命令:
--spider 模擬爬蟲
-q 安靜訪問
-o /dev/null 不輸出
-T --timeout 超時時間
-t --tries 重試次數
[root@web01 ~]# wget --spider -T 5 -q -o /dev/null -t 2 www.baidu.com
[root@web01 ~]# echo $?
0
curl命令:
-I 看響應頭
-s 安靜的 安靜模式。不顯示進度表或錯誤信息。使cURL 不反饋信息。
-o /dev/null 不輸出
-w %{http_code} 返回狀態碼,200
-m 超時時間
[root@web01 ~]# curl www.baidu.com -s &>/dev/null [root@web01 ~]# echo $? 0 [root@web01 ~]# curl -I -m 5 -s -w "%{http_code}\n" -o /dev/null www.baidu.com 200 不用函數的實現寫法 #!/bin/sh if [ $# -ne 1 ] then echo $"usage:$0 url" exit 1 fi wget --spider -q -o /dev/null --tries=1 -T 5 $1 #<==-T指定超時時間,這里的$1為腳本的參數。 if [ $? -eq 0 ] then echo "$1 is yes." else echo "$1 is no." fi 高端專業的函數寫法: [root@oldboy ~]# cat checkurl.sh #!/bin/bash ############################################################## # File Name: checkurl.sh # Version: V1.0 # Author: oldboy # Organization: www.oldboyedu.com # Created Time : 2018-06-07 18:29:19 # Description: ############################################################## usage(){ echo "Usage:$0 url" exit 1 } checkurl(){ wget -q -o /dev/null -t 2 -T 5 $1 if [ $? -eq 0 ] then echo "$1 is ok" else echo "$1 is fail" fi } main(){ if [ $# -ne 1 ] then usage fi checkurl $1 } main $* [root@oldboy scripts]# cat 8_5_1.sh #!/bin/sh function usage() { #<==幫助函數 echo $"usage:$0 url" exit 1 } function check_url() { #<==檢測URL函數。 wget --spider -q -o /dev/null --tries=1 -T 5 $1 #<==這里的$1就是函數傳參。 if [ $? -eq 0 ] then echo "$1 is yes." else echo "$1 is no." fi } function main() { #<==主函數。 if [ $# -ne 1 ] #<==如果傳入的多個參數,則打印幫助函數,提示用戶。 then usage fi check_url $1 #<==接收函數的傳參,即把結尾的$*傳到這里。 } main $* #<==這里的$*就是把命令行接收的所有參數作為函數參數傳給函數內部,常用手法。

 

 

CASE結構條件句

幾乎所有的case都可以用if替代
case "$1" in
    1)
    dddd
    ;;
    2)
    dddd
    ;;
    *)
    dddd
esac

企業應用:
啟動腳本
read 讀入 菜單選擇。

范例9_2:執行shell腳本,打印一個如下的水果菜單:
1.apple
2.pear
3.banana
4.cherry
當用戶輸入對應的數字選擇水果的時候,告訴他選擇的水果是什么,並給水果單詞加上一種顏色(隨意),要求用case語句實現。
范例9_3:給內容加不同的顏色。
內容的顏色用數字表示,范圍為30-37,每個數字代表一種顏色。代碼如下:
echo -e "\033[30m 黑色字 \033[0m" #<==30m表示黑色字。
echo -e "\033[31m 紅色字 \033[0m" #<==31m表示紅色字。
echo -e "\033[32m 綠色字 \033[0m" #<==32m表示綠色字。
echo -e "\033[33m 棕色字 \033[0m" #<==33m表示棕色字(brown),和黃色字相近。
echo -e "\033[34m 藍色字 \033[0m" #<==34m表示藍色字。
echo -e "\033[35m 洋紅字 \033[0m" #<==35m表示洋紅色字(magenta),和紫色字相近。
echo -e "\033[36m 藍綠色 \033[0m" #<==36m表示藍綠色字(cyan),和淺藍色字相近。
echo -e "\033[37m 白色字 \033[0m" #<==37m表示白色字。
說明:不同的數字對應的字體顏色,見系統幫助(來源man console_codes命令的結果)。
范例9_6: 給輸出的字符串加不同的背景顏色。
字的背景顏色對應的數字范圍為40-47,代碼如下。
echo -e "\033[40;37m 黑底白字\033[0m"   #<==40m表示黑色背景。
echo -e "\033[41;37m 紅底白字\033[0m"   #<==41m表示紅色背景。
echo -e "\033[42;37m 綠底白字\033[0m"   #<==42m表示綠色背景。
echo -e "\033[43;37m 棕底白字\033[0m"   #<==43m表示棕色背景(brown),和黃色背景相近。
echo -e "\033[44;37m 藍底白字\033[0m"   #<==44m表示藍色背景。
echo -e "\033[45;37m 洋紅底白字\033[0m"  #<==45m表示洋紅色背景(magenta),和紫色背景相近。
echo -e "\033[46;37m 藍綠底白字\033[0m"   #<==46m表示藍綠色背景(cyan),和淺藍色背景相近。
echo -e "\033[47;30m 白底黑字\033[0m"    #<==47m表示白色背景。

創建case3.sh,定義函數 ,執行函數color $*
創建case4.sh,用.或者source調用函數,打印菜單,輸入數字,顯示不同顏色的字體 范例9_10:利用case語句開發Rsync服務啟動停止腳本,本例采用case語句以及新的思路來實現。 分析: 啟動: rsync
--daemon 停止: pkill rsync killall rsync kill 進程號 ---->最專業的方法 /etc/init.d/rsyncd {start|stop|restart} case

 rsync.sh簡單版

case "$1" in
    start)
        rsync --deamon
        if [ $? -eq 0 ]
        then
            echo "rsync startup ok"
        else
            echo "rsync startup fail"
        fi
        ;;
    stop)
        killall rsync
        if [ $? -eq 0 ]
        then
            echo "rsync stop ok"
        else
            echo "rsync stop fail"
        fi
        ;;
    restart)
        killall rsync && sleep 1 && rsync --deamon
        if [ $? -eq 0 ]
        then
            echo "rsync restart ok"
        else
            echo "rsync restart fail"
        fi
        ;;

    *)
        echo "usage:$0 {start|stop|restart}"
        exit 1
esac

 

升級版

 start(){                                                                                                        
     rsync --deamon
     retval=$?
     if [ $retval -eq 0 ]
     then
         echo "rsync startup ok"
         return $retval
     else
         echo "rsync startup fail"
         return $retval
     fi
 }
 stop(){
     killall rsync
     retval=$?
     if [ $? -eq 0 ]
     then
          echo "rsync stop ok"
                                                                                                  9,1           Top
        return $retval
    else
        echo "rsync restart fail"
        return $retval
    fi  
    }   
case "$1" in
    start)
        start
        # 為了向外傳值
        retval=$?
        ;;  
    stop)
        stop
        retval=$?
        ;;  
    restart)
        restart
        retval=$?
        ;;  

    *)  
        echo "usage:$0 {start|stop|restart}"
        exit 1
esac

 

想要使用chkconfig(man ckhconfig),找到這些信息

RUNLEVEL FILES
       Each service which should be manageable by chkconfig needs two or more commented lines added to its init.d
       script. The first line tells chkconfig what runlevels the service should be started in by default, as well
       as the start and stop priority levels. If the service should not, by default, be started in any runlevels,
       a  -  should  be used in place of the runlevels list.  The second line contains a description for the ser‐
       vice, and may be extended across multiple lines with backslash continuation.

       For example, random.init has these three lines:
       # chkconfig: 2345 20 80  表示在2345這幾個啟動級別上 啟動順序排20 停止順序排80
       # description: Saves and restores system entropy pool for \
       #              higher quality random number generation.

 

在腳本首行加入

#!/bin/bash
# chkconfig: 2345 20 80
# description: rsync start stop and restart   

 

將腳本移動到/etc/init.d/下,並添加執行權限,添加到chkconfig中才能使用

[root@web-01 /server/tools]# mv /etc/init.d/rsync_up.sh /etc/init.d/rsyncd
[root@web-01 /server/tools]# chmod +x /etc/init.d/rsyncd
[root@web-01 /server/tools]# chkconfig --list rsyncd

Note: This output shows SysV services only and does not include native
      systemd services. SysV configuration data might be overridden by native
      systemd configuration.

      If you want to list systemd services use 'systemctl list-unit-files'.
      To see services enabled on particular target use
      'systemctl list-dependencies [target]'.

service rsyncd supports chkconfig, but is not referenced in any runlevel (run 'chkconfig --add rsyncd')
[root@web-01 /server/tools]# chkconfig --add rsyncd
[root@web-01 /server/tools]# chkconfig --list rsyncd

Note: This output shows SysV services only and does not include native
      systemd services. SysV configuration data might be overridden by native
      systemd configuration.

      If you want to list systemd services use 'systemctl list-unit-files'.
      To see services enabled on particular target use
      'systemctl list-dependencies [target]'.

rsyncd             0:off    1:off    2:on    3:on    4:on    5:on    6:off

 

更好一些,調用了系統函數,action。並優化了重復停止的輸出 

#!/bin/bash                                                       
# chkconfig: 2345 20 80
# description: rsync start stop and restart
##############################################################
# File Name: syncd.sh
# Version: V1.0
# Author: pizza
# Created Time : 2019-03-29 22:06:46
# Description:
##############################################################
. /etc/init.d/functions
start(){
    rsync --deamon
    retval=$?
    if [ $retval -eq 0 ]
    then
        action  "rsync startup ok" /bin/true
        return $retval
    else
        action "rsync startup fail" /bin/false
        return $retval
    fi
}
                                                1,1           Top
        return $retval
    fi
    }
case "$1" in
    start)
        start
        # 我了向外傳值
        retval=$?
        ;;
    stop)
        stop
        retval=$?
        ;;
    restart)
        restart
        retval=$?
        ;;

    *)
        echo "usage:$0 {start|stop|restart}"
        exit 1
esac
     

 

開發和系統媲美的腳本

跟完善的查看企業實踐題第11題-制作MySQL腳本

                                                         92,0-1        Bot
#!/bin/bash
# chkconfig: 2345 20 80
# description: rsync start stop and restart
##############################################################
# File Name: syncd.sh
# Version: V1.0
# Author: pizza
# Created Time : 2019-03-29 22:06:46
# Description:
##############################################################
# 定義鎖文件
lockfile=/var/lock/subsys/rsyncd
# 定義變量,指定rsyncd的的pid,是需要自己rsync的conf中去創建

#[root@web-01 /server/tools]# vim /etc/rsyncd.conf
#pid file=/var/run/rsyncd.pid    

srsync_pid_file_path=/var/run/rsyncd.pid
. /etc/init.d/functions
start(){
    rsync --deamon
    retval=$?
    if [ $retval -eq 0 ]
    then
        action  "rsync startup ok" /bin/true
        touch $lockfile
        return $retval
    else
        action "rsync startup fail" /bin/false
        return $retval
    fi
}
stop(){
    # 為了在重復停止操作的時候,不提示,將其扔到黑洞
    if test -s "$rsyncd_pid_file_path"
    then
        rsyncd_pid=`cat $rsyncd_pid_file_path`
        # 判斷進程號是不是真實存在
        if (kill -0 $rsyncd_pid &>/dev/null)
        then
            kill $rsyncd_pid

            retval=$?
            if [ $? -eq 0 ]
            then
                action "rsync stop ok" /bin/true
                rm -f $lockfile
                return $retval
            else
                action "rsync stop fail" /bin/false
                return $retval
            fi
        else
            echo "rsyncd process is not exist."
            return 2
        fi
    else
        echo "$srsync_pid_file_path is not exits,or rsyncd doesnot start"
    fi
}
restart(){
    killall rsync && sleep 1 && rsync --deamon
    retval=$?
    if [ $? -eq 0 ]
    then
        action "rsync restart ok" /bin/true
        return $retval
    else
        action "rsync restart fail" /bin/false
        return $retval
    fi
    }
case "$1" in
    start)
        start
        # 我了向外傳值
        retval=$?
        ;;
    stop)
        stop
        retval=$?
        ;;
    restart)
        restart
        retval=$?
        ;;

    *)
        echo "usage:$0 {start|stop|restart}"
        exit 1
esac
  

 

case總結

1、case語句和if條件句的使用性

case語句比較適合變量較少且為固定的數字或者字符串集合的情況(非不確定內容,如范圍)

2、if和case的常用應用場景

case只要寫服務的啟動腳本,一般情況下,傳參不同且具有少量的字符串,其使用范圍較窄

if就是取值判斷、比較,應用比case更廣,幾乎所有的case語句都可以用if條件語句實現。

3、case語句的特點和優勢

它相當於多分支的if/elif/else語句,但是case語句的優勢是更規范。易讀

 

while循環

循環語句命令常用於重復執行一條指令或一組指令,直到條件不滿足停止,Shell腳本語言的循環語句常見的有while、until、for以及select循環語句。 while循環語句主要用來重復執行一組命令或語句,在企業實際應用中,常用於守護進程或持續運行的程序,除此以外,大多數循環都會用后文即將講解 的for循環語句。

while true
do
    uptime >> /tmp/uptime.log
    sleep 2 # 暫停2s
    usleep 2000 # 微秒                                                                                              
done

 

腳本進程管理命令

 

    后台運行  &、nohup、screen(運維人員)

 為什么要用后台運行,防止你在執行重要命令的時候,網絡宕機

進程管理的其他常見命令

范例1:請使用while循環對下面的腳本進行修改,是的當執行腳本時,每次執行完腳本后,不退出腳本,而是提示用戶輸入

while true
do
    read -p "請輸入兩個數字:" a b
    if [ -z $b ]
    then                                                                                
        echo "請輸入兩個數字"
        continue
    fi
    expr 10 + $a + $b &>/dev/null
    if [ $? -ne 0 ]
    then
        echo "請輸入兩個數字"
        continue
    fi
    echo "a+b=$(($a+$b))"
done

 

范例2:猜數字游戲。首先讓系統隨機生成一個數字,給這個數字定一個范圍(1-60),讓用戶輸入猜的數字,對輸入進行判斷,如果不符合要求,就給予高或低的提示,猜對后則給出猜對用的次數,請用while語句實現。

提示:可以賦予一個猜水果的價格游戲。

1、給數字定范圍(1-60)
RANDOM隨機數,它的范圍是0-32767
[root@web-01 /server/tools]# echo $RANDOM
9279
為隨機數取模。控制在1-60
[root@web-01 /server/tools]# echo $((RANDOM%60))
11
2、用戶輸入數字
read -p “請輸入數字:” num

3、對比,直到正確才推出
while 
4、代碼:
random="$(($RANDOM%60))"
#做計數
count=0
echo $random
while true
do
    read -p "請輸入數字:" num
    ((count++))
    if [[ $num -lt $random ]]
    then
        echo "低了"
        continue
    elif [[ $num -gt $random ]]
    then
        echo "高了"
        continue
    elif [[ $num -eq $random ]]                                          
    then
        echo "恭喜你,猜對了,一共猜了$count次"
        exit 0
    else
        echo "請輸入數字"
    fi
done

還可以加入函數,其他的限制內判斷,使腳本更完善

 

范例3:分析Apache訪問日志(access_2010-12-8.log)日志每行訪問字節數對應字段數字相加,計算出的訪問量。給出實現程序,請用while循環實現。(3分鍾)

方式1:在while循環結尾done通過輸入重定向指定讀取的文件。
while read line
do
    cmd
done<FILE
方式2:使用cat讀取文件內容,然后通過管道進入while循環處理。
cat FILE_PATH|while read line
do
    cmd
done
方式3:采用exec讀取文件后,然后進入while循環處理。
exec <FILE
sum=0
while read line
do
    cmd
done

 

體驗

while read line
do
    echo $line
    sleep 1
done < ./while_01.sh                                                     
~                                                                        
~                                                                        
                                                                      
"while_readline.sh" [New] 13L, 320C written            
[root@web-01 /server/tools]# sh while_readline.sh
#!/bin/bash   
##############################################################
# File Name: while_01.sh
# Version: V1.0
# Author: pizza
# Created Time : 2019-03-30 07:19:26
# Description:
##############################################################
while true
do
uptime >> /tmp/uptime.log
sleep 2 # 暫停2s
usleep 2000 # 微秒
done

 

體驗2

[root@web-01 /server/tools]# seq 10 >>num.log
腳本
sum=0
while read line
do
    ((sum+=line))

done<./num.log
echo $sum     
執行
[root@web-01 /server/tools]# sh while_num_add.sh
55

 

答案

sum=0
awk '{print $10}' access_2010-12-8.log |grep -v -|while read line
do
    ((sum+=line))
done
echo sum 
# 已經計算了,但是最后的結果是0
# 這是因為執行了子shell
# 使用下面的方法可以成功輸出                                             

sum=0
awk '{print $10}' access_2010-12-8.log |grep -v - > any_sum.log
do
    ((sum+=line))
done<./any_sum.log
echo sum 

 

 小結

1、while循環的特長是執行守護進程,以及實現我們希望循環不退出持續執行的應用

擅長用於頻率小於1分鍾循環處理,其他的while循環幾乎都可以被for以及定時任務crond替代

2、if、for最常用,然后是while(守護進程),case(服務啟動腳本)

Shell腳本中各個語句的使用場景

  1、條件表達式,用於簡短的條件判斷及輸出(文件是否存在,字符串是否為空)

  2、if取值判斷,多用於不同值數量較少的情況

  3、for正常的循環應用處理,最常用

  4、while多用於守護進程,無限循環(要加sleep,usleep,控制pinlv)應用

  5、case 多用於服務啟動腳本,打印菜單可用select語句,不過很少用,都用cat的here文檔方法替代

  6、函數用途主要指編碼邏輯清晰,減少重復語句開發

for循環

for循環語句和while循環語句類似,但for循環語句主要用於執行次數有限的循環,而不是用於守護進程以及無限循環。for循環語句常見的語法有兩種, 下面將在不同的語法中對for循環語句進行詳盡的講解。

..

范例1:用for循環豎向打印1、234、5共5個數字。
范例2:通過開發腳本實現僅設置sshd rsyslog crond network sysstat服務開機自啟動。
范例3:計算從1加到100之和。
范例4:在Linux下批量修改文件名,將文件名中的“_finished”去掉。
准備測試數據,如下。
[root@oldboy test]# mkdir /oldboy -p
[root@oldboy test]# cd /oldboy
[root@oldboy oldboy]# touch stu_102999_1_finished.jpg stu_102999_2_finished.jpg stu_102999_3_finished.jpg 
[root@oldboy oldboy]# touch stu_102999_4_finished.jpg stu_102999_5_finished.jpg
[root@oldboy oldboy]# ls -l
總用量 0
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_1_finished.jpg
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_2_finished.jpg
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_3_finished.jpg
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_4_finished.jpg
-rw-r--r-- 1 root root 0 9月   5 10:43 stu_102999_5_finished.jpg

ls *.jpg|awk -F "_finished" '{print "mv",$0,$1$2}'|bash
rename "_finished" "" *.jpg
for file in `ls ./*.jpg`
do
    mv $file `echo ${file/_finished/}`
done

 

范例1答案

for n in 1 2 3 4 5  或者 {1..5}  或者seq 5 
do
    echo $n
done
echo "---------"
for ((i=1;i<=5;i++))
do
    echo $i
done                                                                                                                                                                                                                                                                               
"for_printnum.sh" [New] 18L, 350C written              
[root@web-01 /server/scripts]# sh for_printnum.sh
1
2
3
4
5
---------
1
2
3
4
5

 

范例2答案

for name in sshd rsyslog crond network sysstat
do
    echo "chkconfig $name on"                                            
done

相當於在命令行執行
[root@web-01 /server/scripts]# chkconfig |grep 3:on |awk '{print "chkconfig",$1,"off"}'|bash

 

范例3

1、for循環
2、while循環
3、算法 

 

范例4

1mv $file 'echo ${file/_finished/}'
2、不用for循環
[root@web-01 /server/scripts]# ls *.jpg|awk -F "_finished" '{print $0,$1$2}'
3、rename  from  to  file
rename  _finished ""  *.jpg

 

循環控制語句break、continue、exit、return

上述命令中breakcontinue在條件語句及循環語句(forwhileif等)中用於控制程序的走向,

exit用於終止所有語句並退出當前腳本,除此之外,exit還可以返回上一次程序或命令的執行狀態值給當前Shell

return類似exit,只不過return用於函數內部返回函數執行的狀態值

break n    如果省略n表示跳出整個循環,n 表示跳出循環的層數
continue n    如果省略n表示跳過本次循環,忽略本次循環的剩余代碼,進入循環的下一次循環。n 表示退到第n層繼續循環
exit n    退出當前shell程序,n為上一次程序執行的狀態返回值。n也可以省略,再下一個shell里可通過$?接收exit n的n值
return n    用於在函數里,作為函數的返回值,用於判斷函數執行是否正確。再下一個shell里可通過$?接收exit n的n值

 

 

Shell編程數組應用實踐

為什么會產生shell數組

通常在開發Shell腳本時,我們定義變量采用的形式為a=1;b=2;c=3,可如果有多個變量呢?這時再一個一個定義很費勁,並且多個不確定的變量內容,也難以進行變量定義,此外快速讀取不同變量的值也是一件很痛苦的事情,於是數組就誕生了,就是為了解決上述問題而來的

什么是Shell數組

 

如果讀者有過其他語言的編程經歷,那么想必會熟悉數組的概念。簡單地說,Shell的數組就是把有限個元素(變量或字符內容)用一個名字命名,然后用編號對它們進行區分的元素集合。這個名字就稱為數組名,用於區分不同內容的編號就稱為數組下標。組成數組的各個元素變量稱為數組的元素,有時也稱為下標變量。

 

有了Shell數組后,就可以用相同名字引用一系列變量及變量值,並通過數字(索引)來識別使用它們。在許多場合,使用數組可以縮短和簡化程序開發。


數組的本質還是變量,是特殊的變量形式
array=(1 2 3 4 5)

 

Shell數組的定義*****
    方法1:推薦,用小括號把變量值括起來賦值給數組變量,中間用空格分割
    array=(one two three four)
    方法2:用小括號把變量值括起來,同時采用鍵值對的形式賦值
    array=([0]=one [1]=two [2]=three [3]=four)
    方法3:通過分別定義數組變量的方式
    [root@web01 ~]# array[0]=one
    [root@web01 ~]# array[1]=two
    [root@web01 ~]# array[2]=three
    [root@web01 ~]# array[3]=four
    [root@web01 ~]# echo ${array[@]}
    one two three four
    方法4:命令的結果放到數組里,推薦。動態定義數組變量,使用命令的輸出結果作為數組的內容
    array=(`ls /server/scripts`)

說明:還可以使用declare -a array來定義數組類型,但是比較少這樣用。


操作數組元素
打印單個數組元素用${數組名[下標]},當未指定數組下標時,數組的下標是從0開始。
使用*或者@可以得到整個數組內容。
用${#數組名[@或*]}可以得到數組長度,這和前文講解的變量子串知識是一樣的,因為數組也是變量,只不過是特殊的變量,因此也適合變量的子串替換等知識。

讀取數組內容:*****
[root@web01 ~]# array=( 1 2 3 4 5)
[root@web01 ~]# echo ${array[0]}
1
[root@web01 ~]# echo ${array[1]}
2
[root@web01 ~]# echo ${array[2]}
3
[root@web01 ~]# echo ${array[3]}
4
[root@web01 ~]# echo ${array[4]}
5
[root@web01 ~]# echo ${array[5]}

[root@web01 ~]# echo ${array[*]}
1 2 3 4 5
[root@web01 ~]# echo ${array[@]}
1 2 3 4 5
[root@web01 ~]# echo ${#array[@]}
5
[root@web01 ~]# echo ${#array[*]}
5

給數組增加內容:
[root@web01 ~]# array[5]=oldboy   <==增加下標為5的數組元素。
[root@web01 ~]# echo ${#array[*]}
6
[root@web01 ~]# echo ${array[*]}
1 2 3 4 5 oldboy

刪除數組元素:
[root@web01 ~]# unset array[1]
[root@web01 ~]# echo ${array[*]}
1 3 4 oldboy
[root@web01 ~]# unset array[0]
[root@web01 ~]# echo ${array[*]}
3 4 oldboy

數組賦值:
[root@web-01 /server/scripts]# array[4]=999
[root@web-01 /server/scripts]# echo ${array[*]}
1 2 3 4 999 6

數組的刪除:
因為數組本質上還是變量,因此可通過“unset 數組[下標]”清除相應的數組元素,
如果不帶下標,表示清除整個數組的所有數據。
[root@web-01 /server/scripts]# unset array[1]  刪除單個元素
[root@web-01 /server/scripts]# echo ${array[*]}
1 3 4 999 6
[root@web-01 /server/scripts]# unset array    刪除整個數組
[root@web-01 /server/scripts]# echo ${array[*]} 沒有數據輸出了

數組內容的截取和替換:
這里和前文變量子串的替換是一樣的,因為數組是特殊的變量
[root@web-01 /server/scripts]# echo ${array[*]:1:3}  從下表為1的元素截取3個元素
2 3 4
替換 和sed命令,和變量子字符串的替換 很像,是一樣的
[root@web-01 /server/scripts]# echo ${array[*]/1/999}
999 2 3 4 5 6 7 8 9 9990
[root@web-01 /server/scripts]# echo ${array[*]}  該操作不會改變原數組,要改變請參考賦值修改
1 2 3 4 5 6 7 8 9 10

數組也是變量,因此也適合於前面講解過的變量的子串處理的功能應用。
數組的其他相關知識通過man bash然后搜Arrays來了解。

數組元素部分內容的刪除如下:
[root@oldboy data]# array=(one two three four five)
[root@oldboy data]# echo ${array[@]}               
one two three four five
[root@oldboy data]# echo ${array[@]#o*}    #<==從左邊開始匹配最短的,並刪除。
ne two three four five
[root@oldboy data]# echo ${array1[@]##o*}  #<==從左邊開始匹配最長的,並刪除。
two three four five
[root@oldboy data]# echo ${array[@]%f*}    #<==從右邊開始匹配最短的,並刪除。
one two three
[root@oldboy data]# echo ${array[@]%%f*}   #<==從右邊開始匹配最長的,並刪除。
one two three

使用for循環打印數組元素
array=(1 2 3 4 5)
for n in ${array[*]}
do
    echo $n
done
echo =====================
#i為數組下標
for ((i=0;i<${#array[*]};i++))
do
    echo ${array[i]}
done 

array=([1]=one [2]=two [3]=three) 
array[0]=a;array[1]=b;array[2]=c
array=($(命令))
或
array=(`命令`)

 

shell數組企業面試題

1、利用bash for循環打印下面這句話中字母數不大於6的單詞(某企業面試真題)。

I am pizza teacher welcome to luffy training class

array=(I am oldboy teacher welcome to oldboy training class)

for word in ${array[*]}
#或者
#for ((i=0;i<=${
array[*];i++})) do if [ ${#word} -lt 6 ]
  # if [ ${#array[i]} -lt 6 ]
then echo $word
   # echo
array[i] fi done

 

    

 

第十四章 編程規范
第十五章 腳本調試
第十六章 vim配置
第十七章 trap
第十八章 expect
第十九章 企業案例實戰

第十九章 
企業面試題1:
分析:
1、獲取隨機小寫字符。
echo $RANDOM$(date +%N)|md5sum|tr "[0-9]" "a-z"|cut -c 2-11

2、for循環

企業面試題3:
101..10
[root@db03 ~]# seq -w 10
01
02
03
04
05
06
07
08
09
10
[root@db03 ~]# echo ${01..10}
-bash: ${01..10}: bad substitution
[root@db03 ~]# echo {01..10}
01 02 03 04 05 06 07 08 09 10

2echo $RANDOM|md5sum|cut 1-8
3、for循環批量設置用戶和密碼。

企業面試題4:

1、如何判斷機器是否是活的。
ping 10.0.0.53 -c 2 -W 3 有返回。
nmap -sP 10.0.0.0/24

2.for循環

#!/bin/sh
CMD="nmap -sP"
Ip="10.0.0.0/24"
$CMD $Ip|awk '/Nmap scan report for/ {print $NF}'

http://blog.51cto.com/oldboy/1632876
10,11,18,19,2013,6

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM