Linux系統shell腳本

                   

                       Linux系統shell腳本

 

shell腳本編程:

      基礎編程:

      程序:指令+數據

 程序編程風格:

    過程式:以指令為中心,數據服務于指令

    對象式:以數據為中心,指令服務于數據

 程序的執行方式:

     計算機:運行二進制指令;

編程語言:

    低級:匯編

    高級:編譯、解釋

        編譯:高級語言—–>編譯器——–>目標代碼 (Java、c#

        解釋:高級語言—–>解釋器——–>機器代碼 (shell、Perl、Python

 編程基本概念:

     編程邏輯處理方式:

       順序執行

      循環執行

      選擇執行

 shell編程:過程式、解釋執行

       編程語言的基本結構:

      數據存儲:變量數組

      表達式:a + b

      語句:if

 shell腳本基礎:

   shell腳本是包含一些命令或聲明,并符合一定格式的文本文件;

    格式要求:首行shabang機制

     #!/bin/bash

    #!/usr/bin/python

    #!/usr/bin/perl

 shell 腳本的用途:

   自動化常用命令

  執行系統管理和故障排除

  創建簡單的應用程序

  處理文本或文件

 shell腳本的創建:

       第一步:使用文本編輯器來創建文本文件;

         第一行必須包括shell聲明:

          #!/bin/bash

          添加注釋行:

          注釋行以#開頭

          添加運行命令:

         …………………….

       第二步:運行腳本文件:

           給予執行權限,在命令行上指定腳本的絕對路徑或相對路徑

          直接運行解釋器,將腳本作為解釋器程序的參數

 腳本調試:

      檢測腳本中的語法錯誤:

       bash  -n /path/to/somescript

      調試執行腳本:

       bash  -x /path/to/somescript

 shell變量應用:

      本地變量:生效范圍為當前shell進程,對當前shell的子shell及其它shell進程均無效;  

     環境變量:生效范圍為當前shell進程及其子shell進程;

     局部變量:生效范圍為當前shell進程中某代碼片段(通常指函數);

 變量命名法則:

     1、不能使用程序中的保留字,例如:if、for等;

    2、只能使用數字、字母、及下劃線,且不能以數字開頭;

    3、見名知意;

    4、統一命名規范;

本地變量基本格式:

     變量名=變量值

     例:

      [root@centos7 ~]# day=sunday

      [root@centos7 ~]# echo $day

      sunday

      [root@centos7 ~]#

 注意:當變量名稱容易和緊跟其后的其他字符相混淆時,需要添加{ }”將其包圍起來進行區分,否則將無法確定正確的變量名。

         例:

          [root@centos7 ~]# day=sunday

         [root@centos7 ~]# echo ${day}hayyp

          sundayhayyp

         [root@centos7 ~]#

為變量賦值的常用方法:

       在等號=”后面直接指定變量內容是為變量賦值的最基本的方法,除此之外我們還可以使用 “雙引號”、“單引號”、“反撇號”、“read命令”。

       雙引號:

           使用雙引號時,允許在雙引號的范圍內使用$符號來引用其他變量的值;

            “ ”:弱引用,雙引號中可以引用其他變量的值;

           用法:name=root”   或  name=$USER

                      例:

                       [root@centos7 ~]# echo $day

                      sunday

                      [root@centos7 ~]# today="today is $day"

                      [root@centos7 ~]# echo $today

                      today is sunday

                      [root@centos7 ~]#

       單引號:

           使用單引號時,將不允許在單引號的范圍內引用其他變量的值;在單引號中$”符或其他任何符號將作為普通字符看待。

          ‘ ’:強引用,單引號中變量引用不會被替換為變量值,都當做普通字符看待;

                       例:

                        [root@centos7 ~]# echo $day

                       sunday

                       [root@centos7 ~]# today='today is $day'

                       [root@centos7 ~]# echo $today

                       today is $day

                       [root@centos7 ~]#

       反撇號:

         使用反撇號時,允許將執行特定命令的輸出結果賦值給變量;

         用法:name=`command`   或  name=$(command)

                         例:

server_ip=$(ifconfig | sed -n "2p" | grep -E -o '(([0-9]|[1-9][0-9]|1[0-9]{2}| 2[0-4][0-9]|25[0-    5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])' | head -1 )

               

        login_time=`date +%F-%T`

        host_name=`hostname`     

 read命令:

         我們可以使用bash的內置命令read來給變量賦值,read命令可以從終端鍵盤讀取輸入,實現簡單的交互過程。read將從標準輸入讀入一行內容,并以空格為分隔符,將讀入的各字段分別賦值給列表中指定的變量,多余的內容賦值給最后一個變量。

         為了使交互操作更加友好,提高易用性,我們可以結合-p”選項來設置提示信息,用于告知用戶應該輸入的內容。

             例:

               [root@centos7 profile.d]# read -p "please input a number :" number

              please input a number :123

              [root@centos7 profile.d]# echo $number

              123

              [root@centos7 profile.d]#

      顯示已定義的所有變量(環境變量和本地變量局部變量):set命令

      刪除本地變量:unset 變量名 (可以指定一個或多個變量名做參數)

 環境變量:

            為了使用戶定義的本地變量在所有的子shell環境中能夠繼續使用,減少重復設置工作,可以使用export命令將指定的變量設置為“全局變量”。export命令可以同時使用多個變量名作為參數,變量名之間以空格分隔。

              用法:1、 export  變量名=變量值

                            

                   2、  變量名=變量值

                        export  變量名

                             

                   3declare  -x  變量名=變量值

                      declare  -r  變量名=變量值(只讀變量,不能修改和刪除)

                例:

                 現在在子shell中也可以使用父shell定義的環境變量

                 [root@centos7 Desktop]# export day=sunday

                 [root@centos7 Desktop]# echo $day

                 sunday

                 [root@centos7 Desktop]# bash

                 [root@centos7 Desktop]# echo $day

                 sunday

                 [root@centos7 Desktop]#

顯示所有環境變量:

        export

        env

        printenv

        declare -x

 刪除環境變量:

     unset   變量名

 只讀變量:

      只讀變量:只能聲明,不能修改和刪除;

      readonly  變量名=變量值

      declare  -r  變量名=變量值

       例:

        [root@centos7 Desktop]# readonly today="today is sunday"

        [root@centos7 Desktop]# declare -r year=2016

 位置變量:

      位置變量:用于讓shell腳本在執行過程中可以調用命令行中給出的位置參數;

      位置變量采用$n”的格式,其中“n”是參數的位置序號從( 1-9

         例:$1 $2、$3 $4 、$5 、$6 、$7 、$8 、$9 、

 特殊變量:

     特殊變量是由bash程序預先定義好的一些特殊變量,用戶只能使用這些特殊變量,不能創建新的特殊變量或直接為特殊變量賦值。

                $0:表示命令本身;

               $#:表示傳遞給腳本的參數個數;

               $*:表示所有位置參數的內容,全部參數合為一個字符串;

               $@:傳遞給腳本的所有參數,每個參數為獨立的字符串;

               $?:表示命令執行后返回的狀態,命令退出狀態為0表示命令執行正確,任何非0值得表示命令執行錯誤,(錯誤值1-255之間的任意數值)

               $$:表示當前進程的進程號;

               $!:表示后臺運行的最后一個進程的進程號;

             注:$#$@只在被雙引號包起來的時候才會有差異;

 數值變量運算:

         運算符:    

               “+”:加法運算;

               “”:減法運算;

               “*”:乘法運算,直接用expr運算時需要轉義“\*”;

               “/”:除法運算;

               “**”:乘方;

               “%”:取模運算,又稱為取余運算,即計算數值相除后的余數;

 算數運算格式:

           let  var=算術運算表達式

          var=$[算術運算表達式]

          var=$((算術運算表達式))

          var=$(expr  $ARG1  $OP  $ARG2 )

          declare  -i  var=算術運算表達式

          echo  ‘算術運算表達式’ |bc

                   例:

                   [root@centos7 ~]# let sum=$num1+$num2

                   [root@centos7 ~]# sum=$[$num1+$num2]

                   [root@centos7 ~]# sum=$(($num1+$num2))

                   [root@centos7 ~]# sum=$(expr $num1 \*  $num2)

                   [root@centos7 ~]# sum=`expr $num1 \*  $num2`

                   [root@centos7 ~]# declare -i var=$num1+$num2

 bash有內建的隨機數生成器:$RANDOM 1-32767

      echo $[$RANDOM%50] 0-49之間的隨機數;

       賦值:

       增強型賦值:

      +=  -=  *=  /=  %=

       let  varOPERvalue

       let count +=3 意思是:let  count=count+3

       自增,自減

               let  var+=1意思是:let  var=var+1

               let  var++ 意思是:let  var=var

               let  ++var 意思是:let  var=var+

               let  var-=1 意思是:let  var=var-1

               let  var–  意思是:let  var=var

 邏輯運算:

       運算數:

           真(true、yes、on1

           假(false、nooff0

                與:

                 1 && 1 = 1

                 1 && 0 = 0

                 0 && 1 = 0

                 0 && 0 = 0

                或:

                 1 || 1 = 1

                 1 || 0 = 1

                 0 || 1 = 1

                 0 || 0 = 0

               非:

                  1 = 0

                 ! 0 = 1

   短路法則:

          ~]# command1 && command2

         command1為“假”,則command2不會執行操作;

        反之,command1為“真”,則command2必須執行;

         ~]# command1 || command2

         command1為“真”,則command2不會再執行;

        反之,command1為“假”,則command2必須執行;

 聚集命令:

       有兩種聚集命令的方法:

         1)復合式:date;who | wc -l

        2)子shell:(date; who | wc -l)在子shell中運行的;

 退出狀態:

     進程使用退出狀態來報告成功或失?。?/span>

    $?:變量中保存了最近一次命令執行狀態值;

         0:代表成功;

    1-255:代表失敗;

 條件測試:

         判斷某需求是否滿足,需要由測試機制來實現;

        專用的測試表達式需要由測試命令輔助完成測試過程;

       使用test測試命令時,可以有以下兩種形式;

         test  條件表達式

                    

        [  條件表達式  ]  

        [[  條件表達式  ]]

     注意:條件表達式兩端必須有空白字符,否則為語法錯誤;

 bash的測試類型

      文件測試:

      數值測試:

      字符串測試:

      邏輯測試:

                 文件測試:

                   -d:測試是否為目錄;

                  -e:測試目錄或文件是否存在;

                  -c:測試是否為字符設備文件;

                  -f:測試是否為文件;

                  -r:測試當前用戶是否有權限讀??;

                  -w:測試當前用戶是否有權限寫入;

                  -x:測試當前用戶是否可執行該文件;

                  -L:測試是否為符號鏈接(link)文件;

                  -p:測試是否為管道文件;

                  -S:測試是否為套接字文件;

                  -s:測試文件是否存在且非空;

                  -g:測試是否擁有sgid權限;

                  -u:測試是否擁有suid權限;

                  -k:測試是否擁有sticky權限;

                  -N:測試文件自上一次被讀取之后是否被修改過;

                  -O:測試當前有效用戶是否為文件屬主;

                  -G:測試當前有效用戶是否為文件屬組;

             file1  -ef  file2 :測試file1file2是否指向同一個設備上的相同inode

            file1  -nt  file2 :測試file1是否新于file2;

            file1  -ot  file2 :測試file1是否舊于file2;

               例:

               [root@centos7 ~]# [ -f /etc/passwd ] && echo yes

               yes

               [root@centos7 ~]#

 數值測試:

         數值比較:

        -eq:第1個數等于第二個數;

        -ne:第1個數不等于第二個數;

        -gt:第1個數大于第二個數;

        -lt :第1個數小于第二個數;

        -ge:第1個數大于或等于第二個數;

        -le:第1個數小于或等于第二個數;

                  例:

                     [root@centos7 ~]# sum=`cat /etc/passwd | wc -l`

                     [root@centos7 ~]# echo $sum

                     43

                     [root@centos7 ~]# [ $sum -ge 10 ] && echo "yes"

                     yes

                     [root@centos7 ~]#

 字符串測試:

         ==:是否等于;

         >:是否大于;

         <:是否小于;

        !=:是否不等于;

        =~:左側字符串是否能夠被右側的pattern所匹配;

-z string”:判斷指定的字符串是否為空,空則真,不空則假;

-n sting” :判斷指定的字符串是否不空,空則假,不空則真;

        -a : 并且的意思;

      注意:

        1)字符串要加雙引號;

        2)要使用[[ ]]進行測試;

                例:

                測試$LANG變量是否等于en.US

                 [root@centos7 ~]# [[ $LANG == en.US ]] ||  echo $LANG

                en_US.UTF-8

                [root@centos7 ~]#

                測試abc字符串是否不等于def字符串:

                  [root@centos7 ~]# [[ "abc" != "def" ]] && echo "yes" || echo "no"

                 yes

                 [root@centos7 ~]#

                 測試文件是否為空:

                  [root@centos7 ~]# [[ -z `cat file1` ]] && echo "yes"

                  yes

                  [root@centos7 ~]#

                   測試文件是否為不空:

                  [root@centos7 ~]# [[ -n `cat file1` ]] && echo "yes"

                 yes

                 [root@centos7 ~]#  

                   判斷a是否小于b

                      [root@centos7 ~]# [[ "a" < "b" ]] && echo "yes"

                  yes

                  [root@centos7 ~]#

                  判斷aa是否能夠被模式[ac]匹配:

                   [root@centos7 ~]# [[ aa=~ [ac] ]] && echo "yes" || echo "no"

                  yes

                  [root@centos7 ~]#

 邏輯測試:

       邏輯測試是指同時使用兩個或(多個)條件表達式之間的關系;

       &&邏輯與:表示前后兩個表達式都成立時整個測試結果才為真;否則為假;

      ||邏輯或:表示前后兩個條件至少有一個成立時整個測試結果即為真,否則結果為假;

      !邏輯否:表示當指定的條件表達式不成立時,整個測試結果的命令為真;

           例:

             測試/etc/profile文件是否有執行權限:

              root@centos7 ~]# [ ! -x /etc/profile ] && ls -l /etc/profile || echo "have x mode"

             -rw-r–r–. 1 root root 1750 jun  7  2013 /etc/profile

             [root@centos7 ~]#

 shell腳本編程語言:

         過程式編程語言:

             順序執行

            選擇執行

            循環執行

  if語句的結構:

         單分支的if語句:

              if  條件測試命令

                  then

                     命令序列1

                   fi

         雙分支if語句:

                    if  條件測試命令

                   then

                     命令序列1

                   else

                     命令序列2

                   fi

        多分支的if語句:

                   if  條件測試命令1

                  then

                    命令序列1

                  elif 條件測試命令2

                  then

                    命令序列2

                  else

                    命令序列3

                  fi

   case語句:

             case語句適用于需要進行多重分支的應用情況;

             case支持glob風格的通配符:

              *:任意長度任意字符;

              ?:任意單個字符;

              [ ]:指定范圍內的任意單個字符;

              a|bab語句;

                case 變量引用   in

               pat1

                   命令序列1

               ;;

               pat2

                   命令序列2

               ;;

               pat3)

                   命令序列3

               ;;

               *

                   默認執行的命令序列

                esac

            注意:case行尾必須為單詞“in”,每一模式必須以右括號“)”結束;

                 雙分號;;”表示命令序列的結束;

     循環:

       循環執行:

      將某段代碼重復運行多次;

      循環次數事先已知;

      循環次數事先位置;

      循環時執行進入條件和退出條件;

循環語句:

      for   while    until

 for循環:

     for 變量名  in  列表;do

          循環體

    done

        依次將列表中的元素賦值給“變量名”;每次賦值后即執行依次循環體;直到列表中的元素耗盡,循環結束。

        示例:

         for循環 99乘法表

           1 #!/bin/bash

          2 #multiplicationtables

          3

          4 for i in {1..9}

          5 do

          6   for j in {1..9}

          7       do

          8         if [ $i -ge $j ];then

          9         let sum=$j*$i

         10        echo -n -e "$j*$i=$sum\t"

         11        fi

         12      done

         13      echo

         14 done

         17 unset i

         18 unset j

         19 unset sum

           

             1 #!/bin/bash

            2 #zheng

            3

            4 for ((i=1;i<=9;i++));do

            5

            6     for ((j=1;j<=i;j++));do

            7

            8        echo -e -n "${j}x${i}=$[${i}*${j}]\t"

            9      done

           10       echo

           11 done

           12 unset i

           13 unset j

 while 循環:

       while  條件測試判斷 ;do

            循環體

      done

         條件測試判斷:循環控制條件;進入循環之前,先做一次判斷,每一次循環之后會在次做判斷;條件為true”,則執行依次循環,直到條件測試狀態為false終止循環;

     因此:條件測試判斷一般應該有循環控制變量;而此變量的值會在循環體不斷的被修正;

           進入條件:條件測試判斷為true;

          退出條件:條件測試判斷為false;

        示例:

          測試192.168.3網段的在線主機狀態,并統計在線主機和離線主機的個數;

            1 #!/bin/bash

           2 #grep ServerIp    

           3

           4 ip=192.168.3.

           5 net=1

           6 i=0

           7 j=0

           8

           9 while [ $net -lt 255 ];do

          10     ping -c1 -w1 ${ip}$net &> /dev/null

          11          if [ $? -eq 0 ];then

          12          echo "${ip}$net地址正常"

          13                 let i++

          14         else

          15           echo "${ip}$net地址不正常"

          16                 let j++

          17           fi

          18

          19         let net++

          20 done

          21echo "活躍用戶:$i"

          22 echo "不活躍用戶:$j"

    while循環打印國際圍棋:

            示例:

              1 #!/bin/bash

             2 #while打印國際圍棋

             3 i=1

             4

             5 while [ $i -le 8 ];do

             6

             7         j=1

             8            while [ $j -le 8 ];do

             9             let sum=$i+$j

            10             let  m=$sum%2

            11        #    [ $m -eq 0 ] &&echo -en "\033[41;1m  \033[0m" || echo -en "\033[43;1m  \033[0m"

            12             if [ $m -eq 0 ];then

            13                  echo -en "\033[41;1m  \033[0m"

            14              else

            15                 echo -en "\033[43;1m  \033[0m"

            16               fi

            17             let j++

            18

            19          done

            20      echo

            21    let i++

            22

            23 done

            24 unset i

            25 unset j

            26 unset sum

 until循環:

        until   條件測試判斷;do

             循環體

       done

           進入條件:條件測試判斷為false

          退出條件:條件測試判斷為true

             示例:

               猜數字游戲:

                 1 #!/bin/bash

                 2 #

                 3

                 4 echo "============================="

                 5 suiji=$(($RANDOM%10+1))

                 6 max=10

                 7 zuixiao=1

                 8

                 9 read -p "please  input a number:" num

                10

                11 until [ $num -eq $suiji ];do

                12

                13      echo "你要猜$zuixiao $max之間的數"  

                14

                15          if [ $suiji -gt $num ];then

                16

                17              echo "你猜的太小了"        

                18         else

                19              echo "你猜的太大了"

                20          fi

                21      read -p "please  input a number:" num

                22

                23

                24 done

                25 echo "恭喜你猜對了"

                26 unset suiji

                27 unset max

                28 unset zuixiao

 continue命令:

       continue即“繼續”的意思,用于暫停本次循環,跳轉至循環語句的頂部重新測試條件。

         示例:

             計算100以內所有偶數的和:

               1 #!/bin/bash

              2 #zheng

              3

              4

              5 declare -i addsum=0

              6 declare -i i=0

              7

              8 while  [ $i -le 100 ];do

              9      let i++

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

             11         continue

             12

             13      fi

             14        let addsum+=$i

             15

             16 done

             17

             18

             19 echo "oushu100 sum :$addsum "

             20 unset  addsum

             21 unset  i

 break命令:

       break即“終斷”的意思,用于跳出當前所在的循環體,但是并不退出程序;

         示例:

             100以內偶數的和:(使用while、break命令)

               1 #!/bin/bash

               2 #zheng

               3

               4 declare -i i=0

               5 declare -i sum=0

               6

               7 while true ;do

               8       ((i+=2))

               9      if [ $i -gt 100 ];then

              10

              11             break

              12       fi

              13       ((sum+=$i))

              14 done

              15 echo " $sum"

              16 unset i

              17 unset sumg

         示例:

             100以內偶數的和:(使用until、break命令)

              1 #!/bin/bash

              2 #zheng

              3

              4 declare -i i=0

              5 declare -i sum=0

              6

              7 until false ;do

              8       ((i+=2))

              9      if [ $i -gt 100 ];then

             10             break

             11       fi        

             12       ((sum+=$i))

             13 done  

             14 echo " $sum"

             15 unset i

             16 unset sum

          示例:

             100以內jishu之和:(使用while、break命令:)

 

              1 #!/bin/bash

              2 #zheng

              3

              4 declare -i i=1

              5 declare -i sum=0

              6

              7 while true ;do

              8      if [ $i -gt 100 ];then

              9             break

             10       fi

             11       ((sum+=$i))

             12        ((i+=2))

             13 done

             14 echo " $sum"

             15 unset i

             16 unset sum

   sleep 命令:

                示例:

                  檢測zheng用戶是否登錄系統:

                   1 #!/bin/bash

                  2 #zheng

                  3 #

                  4 while true;do

                  5

                  6      if who | grep "^zheng\>" &> /dev/null;then

                  7           break

                  8      fi

                  9       sleep 5

                 10 done

                 11

                 12 echo "zheng logged on " >> /var/log/messages

 創建無線循環:

         while true;do

            循環體命令

        done

        until  false;do

            循環體命令

        done

 特殊用法:

       while read line;do

          循環體

      done  <  /PATH/FROM/SOMEFILE

      依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將每行賦值給變量line;

               示例:

               掃描/etc/passwd/文件每一行,如發現描述字段為空,則填充用戶名和單位電話為123456;

                1 #!/bin/bash

               2 #zheng

               3

               4 while read line;do

               5   kong=$( echo $line| cut -d: -f5 )

               6      if [ -z "$kong" ];then

               7

               8        user=$(echo $line | cut -d: -f1)

               9        usermod -c "${user} 123456" $user &> /dev/null

              10        echo "add  user:$user"

              11      fi

              12

              13 done </etc/passwd

              14 unset kong

              15 unset user

 特殊用法:

         for循環特殊用法:語法格式

        for (( exp1; exp2; exp3 )); do COMMANDS; done

             for循環的特殊格式:

             for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式));do

                 循環體命令

            done

                控制變量初始化:僅在運行到循環代碼段時執行依次;

                控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,而后在做條件判斷;

               示例:

                  1 #!/bin/bash

                 2 #zheng

                 3

                 4 for (( i=0;i<=100;i++ ));do

                 5

                 6     let sum+=$i

                 7

                 8 done

                 9

                10 echo "$sum"

                11

                12 unset sum

 select 循環與菜單:

       select  變量名 in  list;do

            循環體命令

      done

             select 循環主要用于創建菜單,按數字順序排列的菜單項將顯示在標準錯誤上,并顯示PS3提示符,等待用戶輸入;

             用戶輸入菜單中的某個數字,執行相應的命令

             用戶輸入被保存在內置變量REPLY中;

        select case

               select 是個無限循環體,因此要記住使用break命令退出循環,或使用exit命令終止腳本。也可以按ctrl+c退出循環。

              select 經常和case聯合使用

              for循環類似??梢允÷?in list。此時使用位置參量;

~            示例:

                1 #!/bin/bash

               2 #zheng

               3 #菜單

               4 PS3="你好,想吃點什么,請點序號:"

               5 select menu in 涼菜 熱菜 土豆 梅菜扣肉 雞蛋面;do

               6         echo -n "你點的菜是: "

               7

               8           case $menu in

               9

              10        涼菜)

              11            echo -e "\033[31m涼菜\033[0m"

              12            ;;

              13        熱菜)

              14            echo -e "\033[31m熱菜\033[0m"

              15            ;;

              16        土豆)

              17            echo -e "\033[31m土豆\033[0m"

              18            ;;

              19    梅菜扣肉)

              20            echo -e "\033[31m梅菜扣肉\033[0m"

              21            ;;

              22      雞蛋面)

              23            echo -e "\033[31m雞蛋面\033[0m"

              24            ;;

              25           *)

              26            echo -e "\033[31m sorry,你想吃的本店沒有!\033[0m"

              27            ;;

              28         esac

              29           break

              30

              31

              32 done

 函數介紹:

            函數function是由若干條shell命令組合成的語句塊,實現代碼重用和模塊化編程。

            函數functionshell程序形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運行,而是shell程序的一部分。

            函數和shell程序比較相似,區別在于:

            shell程序在子shell中運行;

            shell函數在當前shell中運行。因此在當前shell中,函數可以對shell中的變量進行修改;

   定義函數:

           函數由兩部分組成:函數名和函數體

    語法一:

   function f_name {

        函數體…….

   }

    語法二:

    f_name() {

          函數體…….

     }

 函數的使用:

     函數的定義和使用:

          可在交互式環境下定義函數

         可將函數放在腳本文件中作為它的一部分

         可放在只包含函數的單獨文件中

     調用:

           函數只有被調用才會執行;

          調用:給定函數名

          函數名出現的地方,會被自動替換為函數代碼

  函數的生命周期:

           函數被調用時創建,返回時終止;

     函數返回值:

          函數有兩種返回值:

          函數的執行結果返回值:

              使用echoprintf命令進行輸出

             函數體中調用命令的輸出結果

 函數的退出狀態碼:

               默認取決于函數中執行的最后一條命令的退出狀態碼

              自定義退出狀態碼,其格式為:

               return 從函數中返回,用最后狀態命令決定返回值

              return 0 無錯誤返回;

              return 1-255 有錯誤返回;

  使用函數文件:

               可以將經常使用的函數存入函數文件,然后將函數文件載入shell;

              函數文件名可以任意選取,但最好與相關任務有某種聯系。例如:function.main;

              一旦函數文件載入shell,就可以在命令行或腳本中調用函數,可以使用set命令查看所有定義的函數,其輸出列表包括已經載入shell的所有函數。

              若要改動函數,首先使用unset命令從shell中刪除函數,改動完畢后,在重新載入此文件;

  載入函數:

            函數文件已創建好,要將它載入shell

            定義函數文件并載入shell的格式:

            . function.main   source function.main要使用正確的路徑

                set命令檢查函數是否已載入,set命令將在shell中顯示所有的載入函數。

  刪除shell函數:

                現在對函數做一些改動,首先刪除函數,使其對shell不可用。使用unset命令完成此功能;

             命令格式:

                unset  function_name

  函數參數:

       函數可以接受參數:

            傳遞參數給函數:調用函數時,在函數名后以空白分隔給定參數列表即可;例如:testfunc arg1 arg2 arg3

             在函數體中,可以使用$1,$2 ……. 調用這些參數;還可以使用$@,$#等特殊變量;

  函數變量:

       變量作用域:

           環境變量:當前shell和子shell有效;

          本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此,本地變量的作用域范圍是當前shell腳本進程文件,包括腳本中函數。

          局部變量:函數的生命周期;函數結束時變量被自動銷毀;

         注意:如果函數中有局部變量,如果其名同本地變量,使用局部變量;

            在函數中定義局部變量的方法:

            local  name=value  

 函數遞歸實例:

         函數遞歸:

             函數直接或間接調用自身

            需注意遞歸層數

              示例:

                 函數遞歸階乘運算

                    1 #!/bin/bash

                   2 #

                   3

                   4 fact () {

                   5     if [ $1 -eq 0 -o $1 -eq 1 ];then

                   6        echo 1

                   7     else

                   8        echo $(($1*`fact $[$1-1]`))

                   9       fi

                  10   }

                  11

                  12 fact $1

          示例:

             在腳本中定義及使用函數

 

               1 #!/bin/bash

               2 #fun1

               3 #zheng

               4 #加減乘除函數庫!

               5

               6 jia() {

               7   sum=$[$1+$2]

               8   echo "$sum"

               9 }

              10

              11 jian() {

              12   sum=$[$1-$2]

              13   echo "$sum"

              14 }

              15

              16 cheng() {

              17   sum=$[$1*$2]

              18   echo "$sum"

              19 }

              20

              21

              22 chu() {

              23   sum=$[$1/$2]

              24   echo "$sum"

              25 }

 定義數組:

   程序=指令+數據

變量:存儲單個元素的內存空間;

數組:存儲多個元素的連續的內存空間;

數組名:整個數組只有一個名字;

數組索引:標號從0開始;

    數組名[索引]

    ${ARRAY_NAME[INDEX]}

注:bash-4及之后的版本,支持自定義索引格式,而不僅僅是0,1,2,3….數組格式,此類數組稱之為關聯數組;

 聲明數組:

    declare  -a ARRAY_NAME  聲明索引數組

    declare  -A ARRAY_NAME  聲明關聯數組

 數組中元素的賦值方式;

    1)一次只賦值一個元素;

         ARRAY_NAME[INDEX]=value

         例:

           [root@centos7 ~]# dongwu[0]=pig

           [root@centos7 ~]# dongwu[1]=dog

           [root@centos7 ~]# echo $dongwu

            pig

           [root@centos7 ~]# echo ${dongwu[1]}

            dog

           [root@centos7 ~]# echo ${dongwu[0]}

            pig

           [root@centos7 ~]#

     2)一次賦值全部元素;

          ARRAY_NAME=val1 val2 val3 val4…….

          例:

           [root@centos7 ~]# weekday=("monday" "tuesday" "wednesday")

           [root@centos7 ~]# echo ${weekday[0]}

           monday

           [root@centos7 ~]# echo ${weekday[1]}

     3)只賦值特定元素    

          ARRAY_NAME=[0]=val1 [3]=val2…..

          注:bash支持稀疏格式的數組;

          例:

           [root@centos7 ~]# gongsi=([1]=baidu [3]=tengxun [4]=ali)

           [root@centos7 ~]# echo ${gongsi[3]}

            tengxun

           [root@centos7 ~]#

      4read  -a  ARRAY_NAME

          例:

           [root@centos7 ~]# read  -a  jiaotong

           huoche qiche feiji  kunchuan

           [root@centos7 ~]# echo ${jiaotong[0]}

           huoche

           [root@centos7 ~]#

       引用數組中的元素:${ARRAY_NAME[INDEX]}

           注意:引用時,只給數組名,表示引用下標為0的元素;

 數組的長度(數組中元素的個數)

      ${#ARRAY_NAME[*]} 表示查看數組中的元素個數;

 ${#ARRAY_NAME[@]}表示查看數組中的元素個數;

 例:

   [root@centos7 ~]# echo ${#jiaotong[*]}

   4

   [root@centos7 ~]#

 ${ARRAY_NAME[*]}  表示查看數組中的所有元素

 ${ARRAY_NAME[@]} 表示查看數組中的所有元素

  例:

   [root@centos7 ~]# echo ${jiaotong[*]}

    huoche qiche feiji kunchuan

   [root@centos7 ~]#  

注意:如果寫成${#ARRAY_NAME} 表示查看數組中第一元素的字符長度;

 示例:生成10個隨機數,并找出其中的最大值;

       1 #!/bin/bash

       2 #zheng

       3 #

       4

       5 declare -a rand

       6 declare -i max=0

       7 for i in {0..9};do

       8

       9      rand[$i]=$RANDOM

      10      echo ${rand[$i]}

      11      if [ ${rand[$i]} -gt $max ];then

      12          max=${rand[$i]}

      13      fi

      14 done

      15 echo "max : $max"

      16 unset rand

      17 unset i

示例:定義一個數組,數組中的元素是/var/log目錄下所有以*.log結尾的文件,統計其下標為偶數的文件中的行數之和;

       1 #!/bin/bash

       2 #zheng

       3 #

       4 declare -a files

       5 files=(/var/log/*.log)

       6 declare -i lines=0

       7

       8 for i in $(seq 0 $[${#files[@]}-1]);do

       9

      10      if [ $[$i%2] -eq 0 ];then

      11         let lines+=$(wc -l ${files[$i]} | cut -d " " -f1)

      12      fi

      13 done

      14 echo "lines :$lines"

      15 unset files

      16 unset lines

      17 unset i

 數組元素切片:

    ${ARRAY_NAME[@]:offset:number}

offset:要跳過的元素個數;

number:要取出的元素個數;省略number時,表還取偏移量之后的所有元素;

 向非稀疏格式數組中追加元素:

ARRAY_NAME[${#array_name[]*}]=value

例:

[root@centos7 testdir]# echo ${weekday[*]}

monday tuesday wednesday

[root@centos7 testdir]# weekday[${#weekday[@]}]=sunday

[root@centos7 testdir]# echo ${weekday[*]}

monday tuesday wednesday sunday

[root@centos7 testdir]#

刪除數組中的某個元素:

unset ARRAY[INDEX]

例:

[root@centos7 testdir]# unset weekday[3]

 關聯數組:

declare  -A ARRAY_NAME (使用關聯數組必須提前聲明)

ARRAY_NAME=[index_name1]=value1  [index_name2]=value2

bash的內置字符串處理工具:

 字符串切片:

   ${var:offset:number}

   offset:要跳過的元素個數;

   number:要取出的元素個數;省略number時,表還取偏移量之后的所有元素;

   取自符串的字串;

   取字符串的最右側的幾個字符:${var:  -length}

   注意:冒號后必須有一個空白字符;

  例:

  [root@centos7 testdir]# echo ${weekday[*]}

   monday tuesday wednesday sunday

  [root@centos7 testdir]# echo ${weekday[@]:1:3}

   tuesday wednesday sunday

  [root@centos7 testdir]# echo ${weekday[@]: -1}

   sunday

  [root@centos7 testdir]#

  基于模式取字串:

      ${var#*word}:其中Word是指定的分隔符;功能:自左而右,查找var變量所存儲的字符串中,第一次出現的word分隔符,刪除字符串開頭至此分隔符之間的所有字符;

     ${var##*word}:其中Word是指定的分隔符;功能:自左而右,查找var變量所存儲的字符串中,最后一次出現的word分隔符,刪除字符串開頭至此分隔符之間的所有字符;

 示例:

 [root@centos7 testdir]# path=/etc/init.d/functions

 [root@centos7 testdir]# echo ${path#*/}

 etc/init.d/functions

 [root@centos7 testdir]# echo ${path##*/}

 functions

 [root@centos7 testdir]#

      ${var%word*}:其中Word是指定的分隔符;功能:自右而左,查找var變量所存儲的字符串中,第一次出現的word分隔符,刪除此字符串至尾部的所有字符;

     ${var%%word*}:其中Word是指定的分隔符;功能:自右而左,查找var變量所存儲的字符串中,最后一次出現的word分隔符,刪除此字符串至尾部的所有字符;

   示例:

  [root@centos7 testdir]# path=/etc/init.d/functions

  [root@centos7 testdir]# echo ${path%/*}

  /etc/init.d

  [root@centos7 testdir]# echo ${path%%/*}

 

  [root@centos7 testdir]#

 查找替換:

     ${var/PATTERN/SUBSTI}:查找var所表示的字符串,第一次被PATTERN所匹配的字符串,將其替換為SUBSTI所表示的自符串;

${var//PATTERN/SUBSTI}:查找var所表示的字符串,所有被PATTERN所匹配的字符串,將其全部替換為SUBSTI所表示的自符串;

  示例:

  [root@centos7 testdir]# name="root:x:0:0::root:bashroot"

  [root@centos7 testdir]# echo ${name/root/ROOT}

  ROOT:x:0:0::root:bashroot

  [root@centos7 testdir]# echo ${name//root/ROOT}

  ROOT:x:0:0::ROOT:bashROOT

  [root@centos7 testdir]#

 ${var/#PATTERN/SUBSTI} 查找var所表示的字符串中,行首被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串;

${var/%PATTERN/SUBSTI} 查找var所表示的字符串中,行尾被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串;

  示例:

 [root@centos7 testdir]# name="root:x:0:0::root:bashroot"

 [root@centos7 testdir]# echo ${name/#root/ROOT}

 ROOT:x:0:0::root:bashroot

 [root@centos7 testdir]# echo ${name/%root/ROOT}

 root:x:0:0::root:bashROOT

 [root@centos7 testdir]#

   注意:PATTERN中使用glob風格的通配符;

 查找刪除:

    ${var/PATTERN}:以PATTERN為模式查找var字符串中第一次的匹配,并刪除;

   ${var//PATTERN}:以PATTERN為模式查找var字符串中所有的匹配,并刪除;

   ${var/#PATTERN}:以PATTERN為模式查找var字符串中行首匹配,并刪除;

   ${var/%PATTERN}:以PATTERN為模式查找var字符串中行尾匹配,并刪除;

  示例:

   [root@centos7 testdir]# name="root:x:0:0::root:bashroot"

   [root@centos7 testdir]# echo ${name/root}

    :x:0:0::root:bashroot

   [root@centos7 testdir]# echo ${name//root}

   :x:0:0:::bash

   [root@centos7 testdir]# echo ${name/#root}

   :x:0:0::root:bashroot

   [root@centos7 testdir]# echo ${name/%root}

   root:x:0:0::root:bash

   [root@centos7 testdir]#

 字符大小寫轉換:

    ${var^^}:把var中的所有小寫字符轉換為大寫;

${var,,}:把var中的所有大寫字符轉換為小寫;

 示例:

[root@centos7 testdir]# name="root:x:0:0::root:bashroot"

[root@centos7 testdir]# echo ${name^^}

ROOT:X:0:0::ROOT:BASHROOT

[root@centos7 testdir]# name1=${name^^}

[root@centos7 testdir]# echo $name1

ROOT:X:0:0::ROOT:BASHROOT

[root@centos7 testdir]# echo ${name,,}

root:x:0:0::root:bashroot

[root@centos7 testdir]#

 變量賦值:

    ${var:-VALUE}:如果var變量為空,或未設置,那么返回value,否則返回var變量的值;

   ${var:=VALUE}:如果var變量為空,或未設置,那么返回value,并將value賦值給var變量;否則,則返回var變量的值;

   ${var:+VALUE}:如果var變量不空,則返回value

   ${var:?ERROR_INFO}:如果var為空,或未設置,那么返回ERROR_INFO為錯誤提示,否則,返回var值;

 高級變量用法:

   shell變量一般是無類型的,但是bash shell提供了declaretypeset兩個命令用于指定變量的類型,兩個命令是完全等價的

declare [options] 變量名

         -r:將變量設置為只讀變量;

         -i:將變量定義為整數型變量;

         -a:將變量定義為數組;

         -f:顯示此腳本前定義過的所有函數名及其內容;

         -F:僅顯示此腳本前定義過的所有函數名;

         -x:將變量聲明為環境變量;

         -l:將變量值轉為小寫字母;

         -u:將變量值轉換為大寫字母;

 間接變量引用:

     如果第一個變量的值是第二個變量的名字,從第一個變量引用第二個變量的值,就稱為間接變量引用;

     variable1=variable2

     variable2=value

 分析:variable1的值時variable2,而variable2又是變量名,variable2的值為value,間接變量引用是指通過variable1獲得變量值value的行為;

bash shell提供了兩種格式實現間接變量引用;

eval  tempvar=\$$variable1

tempvar=${!variabe1}

 示例:

[root@centos7 testdir]# v1=v2

[root@centos7 testdir]# v2=mage

[root@centos7 testdir]# echo ${!v1}

mage

[root@centos7 testdir]#

     

 [root@centos7 testdir]# v1=v2

[root@centos7 testdir]# v2=mage

[root@centos7 testdir]# eval v3=\$$v1

[root@centos7 testdir]# echo $v3

mage

[root@centos7 testdir]#

eval命令:

eval命令將會首先掃描命令行進行所有的置換,然后在執行該命令。該命令適用于那些一次掃描無法實現其功能的變量。該命令對變量進行兩次掃描;

eval命令:先將變量替換成命令,然后在執行該命令)

示例:

[root@centos7 testdir]# host=hostname

[root@centos7 testdir]# eval $host

centos7

[root@centos7 testdir]#

創建臨時文件:

    mktemp命令:創建的臨時文件可以避免沖突,文件名后要至少跟三個大寫的XXX

mktemp  [options]  [TEMPLATE]

           -d:創建臨時目錄;

           –tmpdir=/DIR :指明臨時文件所存放的目錄位置;

   示例:

 創建臨時指定目錄下的文件:

  root@centos7 testdir]# mktemp –tmpdir=/testdir test.XXX

  /testdir/test.7WV

  [root@centos7 testdir]#

創建臨時目錄:

[root@centos7 testdir]# mktemp -d dir.XXX

dir.lKU

[root@centos7 testdir]#

安裝復制文件:

install命令:

     install  [options]  source directory

              -mmode設置權限;默認755

              -oowner 設置屬主;

              -ggroup 設置屬組;

 bash如何展開命令行:

      把命令行分成單個命令詞;

     展開別名;

     展開大括號中的聲明({});

     展開波浪符聲明({});

     命令替換$();

     再次把命令行分成命令詞;

     展開文件通配(* ? [abc]等等);

     準備I/O重定向(< >);

     運行命令;

 防止擴展:

 反斜線(\)會使隨后的字符按愿意解釋

加引號來防止擴展

 單引號防止所有的擴展;

 雙引號也防止所有的擴展,但是以下情況例外:

 $ ——變量擴展

 `——–命令替換

 \——–禁止單個字符擴展

 !——–歷史命令替換

 bash的配置文件:

 按生效范圍劃分,可分為兩類:

全局配置:

/etc/profile

/etc/profile.d/*.sh

/etc/bashrc

個人配置:

~/.bash_profile

~/.bashrc

 shell登錄兩種方式:

 交互式登錄:

 1)直接通過終端輸入用戶名密碼登錄;

 2)使用 su – username 切換的用戶;

   交互式登錄系統依次所執行的文件:

  /etc/profile—–>/etc/profile.d/*.sh——->~/.bash_profile——>~/.bashrc——>/etc/bashrc

非交互式登錄:

      1su  username;

      2)圖形界面下打開終端;

      3)執行腳本;

       非交互式登錄系統依次所執行的文件:

       ~/.bashrc—–>/etc/bashrc——–>/etc/profile.d/*.sh

 profile類文件:

      profile類:為交互式登錄的shell提供配置:

     全局:/etc/profile  /etc/profile.d/*.sh

     個人:~/.bash_profile

     功能:

         1)用于定義環境變量;

         2)運行命令或腳本;

  bashrc類文件:

       bashrc類:為非交互式和交互式登錄的shell提供配置:

       全局:/etc/bashrc

       個人:~/.bashrc

       功能:

          1)定義本地變量

          2)定義命令別名和函數

 編輯配置文件生效:

 修改profilebashrc文件后需要生效

兩種生效方法:

(1)重新啟動shell進程;

(2)使用 . source 使配置文件重新加載;

 bash 退出任務:

 當退出登錄的shell時系統會執行~/.bash_logout文件中的內容

功能:

   1)可以創建自動備份;

   2)刪除臨時文件;

 

      

 

 

 

 

 

 

 

 

 

 

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

(0)
zhengyibozhengyibo
上一篇 2016-09-01 08:50
下一篇 2016-09-01 08:50

相關推薦

  • 設計模式(九)外觀模式Facade(結構型)

    1. 概述      外觀模式,我們通過外觀的包裝,使應用程序只能看到外觀對象,而不會看到具體的細節對象,這樣無疑會降低應用程序的復雜度,并且提高了程序的可維護性。例子1:一個電源總開關可以控制四盞燈、一個風扇、一臺空調和一臺電視機的啟動和關閉。該電源總開關可以同時控制上述所有電器設備,電源總開關即為該系統的外觀模式設計。 2.…

    Linux干貨 2015-07-06
  • Javascript 裝載和執行

    一兩個月前在淘寶內網里看到一個優化Javascript代碼的競賽,發現有不少的人對Javascript的執行和裝載的基礎并不懂,所以,從那天起我就想寫一篇文章,但一直耽擱了。自上篇《瀏覽器渲染原理簡介》,正好也可以承前啟后。 首先,我想說一下Javascript的裝載和執行。通常來說,瀏覽器對于Javascript的運行有兩大特性:1)載入后馬上執行,2)執…

    Linux干貨 2016-08-15
  • 創建目錄樹

    創建目錄樹 [wing@bogon ~]$ mkdir -pv /tmp/mylinux/{bin,boot/grub,dev,etc/{rc.d/init.d,\ sysconfig/network-scripts},\ lib/modules,lib64,proc,sbin,sys,tmp,usr/local{bin,sbin},\ var/{lock,…

    Linux干貨 2017-07-24
  • Centos6.5基于SSL密碼認證部署ELK(Elasticsearch+Logstash+kibana)

    1       簡介 本章我們來介紹Centos6.5基于SSL密碼認證部署ELK(Elasticsearch 1.4.4+Logstash 1.4.2+kibana3),同時為大家介紹如何集合如上組件來收集日志,本章的日志收集主要為大家介紹SYSTEM日志收集. 集中化日志收集主要應用場景是在同一…

    Linux干貨 2015-06-18
  • openvpn安裝配置過程

    前言     之前為了方便遠程辦公時訪問公司的內部系統,如:svn、OA、wiki、禪道等等;通通在防火墻上做了端口映射。然后有個內部系統被黑了,各種弱口令沒辦法。果斷關閉端口映射,看來還是得搭建個VPN服務器,vpn設備感覺大材小用。馬上就想到了開源的openvpn,下面就來介紹openvpn的安裝配置過程。 ope…

    Linux干貨 2015-05-11
  • MySQL高級特性-合并表

    1. Merge Tables         如果愿意的話,可以把合并表看成一種較老的、有更多限制的分區表,但是它們也有自己的用處,并且能提供一些分區表不能提供的功能。 合并表實際是容納真正的表的容器??梢允褂锰厥獾腢NION語法來CREATE TABLE。下面是一個合并表的例子: mysql> &n…

    Linux干貨 2015-04-13
欧美性久久久久