bash shell腳本

  1. 更換系統默認shell

shell類型

  • /bin/sh (已經被 /bin/bash 所取代)
  • /bin/bash (就是 Linux 默認的 shell)
  • /bin/tcsh (整合 C Shell ,提供更多的功能)
  • /bin/csh (已經被 /bin/tcsh 所取代)
  • zsh

Bash shell功能

  • 命令編修能力 (history)~/.bash_history

  • 命令與文件補全功能(tab鍵)

  • 命令別名設置功能(alias)

  • 程序化腳本(shell scripts)

  • 萬用字符(Wildcard)*

特殊符號

符號 內容
# 註解符號:這個最常被使用在 script 當中,視爲說明!在後的數據均不執行
\ 跳脫符號:將“特殊字符或萬用字符”還原成一般字符
| 管線 (pipe):分隔兩個管線命令的界定(後兩節介紹);
; 連續指令下達分隔符號:連續性命令的界定 (注意!與管線命令並不相同)
~ 使用者的主文件夾
$ 取用變量前置字符:亦即是變量之前需要加的變量取代值
& 工作控制 (job control):將指令變成背景下工作
! 邏輯運算意義上的“非” not 的意思!
/ 目錄符號:路徑分隔的符號
>, >> 數據流重導向:輸出導向,分別是“取代”與“累加”
<, << 數據流重導向:輸入導向 (這兩個留待下節介紹)
’ ’ 單引號,不具有變量置換的功能 ($ 變爲純文本)
" " 具有變量置換的功能! ($ 可保留相關功能)
` ` 兩個“ ` ”中間爲可以先執行的指令,亦可使用 $( )
( ) 在中間爲子 shell 的起始與結束
{ } 在中間爲命令區塊的組合!

變量

  1. 變量的取用 echo

    echo $varible

    echo ${varible}

  2. 變量設定規則

    • =設置變量,且前後不能有空格

    • 雙引號內的特殊字符如 $ 等,可以保有原本的特性,如下所示: var="lang is $LANG"echo $var可得lang is zh_TW.UTF-8

    • 單引號內的特殊字符則僅爲一般字符 (純文本),如下所示: var='lang is $LANG'echo $var可得lang is $LANG

    • 使用\轉義特殊字符

    • 使用``

    • export varible使變量變成環境變量

      • 子程序

        在當前這個 shell 的情況下,去啓用另一個新的 shell ,新的那個 shell 就是子程序

      • 在一般的狀態下,父程序的變量無法在子程序內使用。但通過 export 將變量變成環境變量後,就能夠在子程序下面是使用了

    • unset varible取消變量

    • 單引號與雙引號必須成對,否則會報錯

  3. env 列出當前shell環境下所有環境變量

  4. set列出自定義變量和環境變量

  5. $?變量

    $是本shell的線程代號(pid)

    ?是上一個執行命令的回傳值,如果上個指令成功執行,則會回傳一個0;有錯誤否則非0
    在這裏插入圖片描述

  6. export將自定義變量轉成環境變量

  7. 子程序僅會繼承父程序的環境變量, 子程序不會繼承父程序的自訂變量

  8. 變量鍵盤讀取與宣告

    • read讀取來自鍵盤輸入的變量

      read [-pt] varible
      選項與參數:
      -p  :後面可以接提示字符!
      -t  :後面可以接等待的“秒數!”這個比較有趣~不會一直等待使用者啦!
      
    • declare / typeset定義變量的類型

      declare [-aixr] variable
      選項與參數:
      -a  :將後面名爲 variable 的變量定義成爲陣列 (array) 類型
      -i  :將後面名爲 variable 的變量定義成爲整數數字 (integer) 類型
      -x  :用法與 export 一樣,就是將後面的 variable 變成環境變量;
      -r  :將變量設置成爲 readonly 類型,該變量不可被更改內容,也不能 unset
      
      sum=100+300+50
      echo ${sum}  => '100+300+50'
      declare -i sum=100+300+50
      echo ${sum}  => 450
      
      • 變量類型默認爲“字串”,所以若不指定變量類型,則 1+2 爲一個“字串”而不是“計算式”。
      • bash 環境中的數值運算,默認最多僅能到達整數形態,所以 1/3 結果是 0;

數組

#設置數組
array_name=(value1 ... valuen)
array_name=(
value1
valuen
)
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
#讀取數組
${array_name[index]}
#使用@ 或 * 可以獲取數組中的所有元素獲取數組中的所有元素
${my_array[*]}
${my_array[@]}
#使用#獲取數組的長度
echo "數組元素個數爲: ${#my_array[*]}"
echo "數組元素個數爲: ${#my_array[@]}"

Shell scripts

  1. 爲啥學習
    • 自動化管理
    • 追蹤與管理系統
    • 簡單入侵偵測
    • 連續指令單一化
    • 簡易的數據處理
    • 跨平臺支持與學習歷程較短
  2. 注意事項
    1. 指令的執行是從上而下、從左而右的分析與執行;
    2. 指令、選項與參數間的多個空白都會被忽略掉;
    3. 空白行也將被忽略掉,並且 [tab] 按鍵所推開的空白同樣視爲空白鍵;
    4. 如果讀取到一個 Enter 符號 (CR) ,就嘗試開始執行該行 (或該串) 命令;
    5. 至於如果一行的內容太多,則可以使用“ [Enter] ”來延伸至下一行;
    6. “ # ”可做爲註解!任何加在 # 後面的數據將全部被視爲註解文字而被忽略!
  3. read指令實現對談式腳本
  4. $(())進行數值運算。僅支持整數
  5. script執行的方式差異
    1. 直接執行:在子程序中執行(變量不會傳到父程序)
      • 當使用前一小節提到的直接指令下達 (不論是絕對路徑/相對路徑還是 ${PATH} 內),或者是利用 bash (或 sh) 來下達腳本時, 該 script 都會使用一個新的 bash 環境來執行腳本內的指令
        在這裏插入圖片描述
    2. 利用source執行:在父程序中執行
      在這裏插入圖片描述

判斷式

  1. test測試

    測試的標誌 代表意義
    1. 關於某個文件名的“文件類型”判斷,如 test -e filename 表示存在否
    -e 該“文件名”是否存在?(常用)
    -f 該“文件名”是否存在且爲文件(file)?(常用)
    -d 該“文件名”是否存在且爲目錄(directory)?(常用)
    -b 該“文件名”是否存在且爲一個 block device 設備?
    -c 該“文件名”是否存在且爲一個 character device 設備?
    -S 該“文件名”是否存在且爲一個 Socket 文件?
    -p 該“文件名”是否存在且爲一個 FIFO (pipe) 文件?
    -L 該“文件名”是否存在且爲一個鏈接文件?
    2. 關於文件的權限偵測,如 test -r filename 表示可讀否 (但 root 權限常有例外)
    -r 偵測該文件名是否存在且具有“可讀”的權限?
    -w 偵測該文件名是否存在且具有“可寫”的權限?
    -x 偵測該文件名是否存在且具有“可執行”的權限?
    -u 偵測該文件名是否存在且具有“SUID”的屬性?
    -g 偵測該文件名是否存在且具有“SGID”的屬性?
    -k 偵測該文件名是否存在且具有“Sticky bit”的屬性?
    -s 偵測該文件名是否存在且爲“非空白文件”?
    3. 兩個文件之間的比較,如: test file1 -nt file2
    -nt (newer than)判斷 file1 是否比 file2 新
    -ot (older than)判斷 file1 是否比 file2 舊
    -ef 判斷 file1 與 file2 是否爲同一文件,可用在判斷 hard link 的判定上。 主要意義在判定,兩個文件是否均指向同一個 inode 哩!
    4. 關於兩個整數之間的判定,例如 test n1 -eq n2
    -eq 兩數值相等 (equal)
    -ne 兩數值不等 (not equal)
    -gt n1 大於 n2 (greater than)
    -lt n1 小於 n2 (less than)
    -ge n1 大於等於 n2 (greater than or equal)
    -le n1 小於等於 n2 (less than or equal)
    5. 判定字串的數據
    test -z string 判定字串是否爲 0 ?若 string 爲空字串,則爲 true
    test -n string 判定字串是否非爲 0 ?若 string 爲空字串,則爲 false。 -n 亦可省略
    test str1 == str2 判定 str1 是否等於 str2 ,若相等,則回傳 true
    test str1 != str2 判定 str1 是否不等於 str2 ,若相等,則回傳 false
    6. 多重條件判定,例如: test -r filename -a -x filename
    -a (and)兩狀況同時成立!例如 test -r file -a -x file,則 file 同時具有 r 與 x 權限時,纔回傳 true。
    -o (or)兩狀況任何一個成立!例如 test -r file -o -x file,則 file 具有 r 或 x 權限時,就可回傳 true。
    ! 反相狀態,如 test ! -x file ,當 file 不具有 x 時,回傳 true
  2. 判斷符號[](常用在if then條件語句中)

    • 在中括號 [] 內的每個元件都需要有空白鍵來分隔;

    • 在中括號內的變量,最好都以雙引號括號起來;

    • 在中括號內的常數,最好都以單或雙引號括號起來。

    • 可以使用上面test中的參數比對

    • # □代表空格
      [  "$HOME"  ==  "$MAIL"  ]
      ["$HOME"=="$MAIL"]
       ↑       ↑  ↑       ↑
      
  3. shell script的默認變數(內建變量)($0,$1)

    /path/to/scriptname  opt1  opt2  opt3  opt4
           $0             $1    $2    $3    $4
    
    • 執行的腳本文件名爲 $0 這個變量,第一個接的參數就是 ​$1

    • $# :代表後接的參數“個數”,以上表爲例這裏顯示爲“ 4 ”;

    • $@ :代表"$1" "$2" "$3" "$4"之意,每個變量是獨立的(用雙引號括起來);

    • $* :代表"$1<u>c</u>$2<u>c</u>$3<u>c</u>$4",其中 <u>c</u> 爲分隔字符,默認爲空白鍵, 所以本例中代表"$1 $2 $3 $4"之意。

    • shift可以造成參數變量號偏移
      在這裏插入圖片描述

條件判斷式

  1. if then

    • 單層判斷

      if [ 條件判斷式 ]; then
        xxxx  # 當條件判斷式成立時,可以進行的指令工作內容;
      fi   # 將 if 反過來寫,就成爲 fi 啦!結束 if 之意!
      
    • 多層判斷

      • `if else

        # 一個條件判斷,分成功進行與失敗進行 (else)
        if [ 條件判斷式 ]; then
          xxx  #當條件判斷式成立時,可以進行的指令工作內容;
        else
           xxx  #當條件判斷式不成立時,可以進行的指令工作內容;
        fi
        
      • if ... elif ... elif ... else

        # 多個條件判斷 (if ... elif ... elif ... else) 分多種不同情況執行
        if [ 條件判斷式一 ]; then
          xxx  #當條件判斷式一成立時,可以進行的指令工作內容;
        elif [ 條件判斷式二 ]; then
          xxx  #當條件判斷式二成立時,可以進行的指令工作內容;
        else
         xxx   #當條件判斷式一與二均不成立時,可以進行的指令工作內容;
        fi  
        
  2. case...esac判斷

    case  $變量名稱 in   #關鍵字爲 case ,還有變量前有錢字號
      "第一個變量內容"#每個變量內容建議用雙引號括起來,關鍵字則爲小括號 )
        程序段
        ;;            #每個類別結尾使用兩個連續的分號來處理!
      "第二個變量內容")
        程序段
        ;;
      *)                  #最後一個變量內容都會用 * 來代表所有其他值
        #不包含第一個變量內容與第二個變量內容的其他程序執行段
        exit 1
        ;;
    esac                  #最終的 case 結尾!“反過來寫”思考一下!
    
  3. 利用函數功能

    function fname() {
        程序段
    }
    
    • function 也是擁有內置變量

      函數名稱代表示 $0 ,而後續接的變量也是以$1, $2

循環

  1. 不定循環

    • while do done

      while [ condition ]  #中括號內的狀態就是判斷式
      do            #do 是循環的開始!
          #程序段落
      done          #done 是循環的結束
      
    • until do done 與while相反

      #當 condition 條件成立時,就終止循環, 否則就持續進行循環的程序段。
      until [ condition ]
      do
          程序段落
      done
      
  2. 固定循環

    for var in con1 con2 con3 ...
    do
        程序段
    done
    #第一次循環時, $var 的內容爲 con1 ;
    #第二次循環時, $var 的內容爲 con2 ;
    #第三次循環時, $var 的內容爲 con3 ;
    
    for (( 初始值; 限制值; 執行步階 ))
    do
        程序段
    done
    

    Tips 1到100,除了使用 $(seq 1 100) 之外,你也可以直接使用 bash 的內置機制來處理喔!可以使用 {1…100} 來取代 $(seq 1 100) ! 那個大括號內的前面/後面用兩個字符,中間以兩個小數點來代表連續出現的意思!例如要持續輸出 a, b, c…g 的話, 就可以使用“ echo {a…g} ”這樣的表示方式!seq是sequence是連續的縮寫

  3. shell scripts的調試

    sh [-nvx] scripts.sh
    選項與參數:
    -n  :不要執行 script,僅查詢語法的問題;
    -v  :再執行 sccript 前,先將 scripts 的內容輸出到屏幕上;
    -x  :將使用到的 script 內容顯示到屏幕上,這是很有用的參數!
    
發佈了38 篇原創文章 · 獲贊 0 · 訪問量 5677
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章