O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Bash shell script 教學

9.774 visualizações

Publicada em

Bash shell script 教學

Publicada em: Software
  • Seja o primeiro a comentar

Bash shell script 教學

  1. 1. BASH SHELL SCRIPT 教學 1
  2. 2. 建立第一個 HELLO WORLD 腳本 (SCRIPT) #!/bin/bash echo "hello world" 儲存成 hello.sh 2
  3. 3. 執行腳本 $chmod +x hello.sh $./hello.sh 或者 $bash hello.sh 3
  4. 4. 指令與參數 (COMMAND AND ARGUMENT) bash 會依照空格本分辨指令及參數 指令 參數1 參數2 … 參數n $touch a b c $touch a b c # 即使超過一個空格也沒問題 4
  5. 5. 指令與參數 5 $echo "Today Very Big" Today Very Big $echo Today Very Big Today Very Big $echo Today Very Big Today Very Big echo 後面接了三個參數 echo 後面只接了一個參數 (字串) 因此,會輸出含空白的 Today Very Big
  6. 6. 參數的設定 $var=abc O $var = abc X $var =abc X 6 變數與 = 之間不能有空白,有空白會被當成指令的參數
  7. 7. 參數的使用 7 $touch "you are my friend.mp3" $file="you are my friend.mp3" $rm $file rm: cannot remove `you': No such file or directory rm: cannot remove `are': No such file or directory rm: cannot remove `my': No such file or directory rm: cannot remove `friend.mp3': No such file or directory rm $file 展開會,會變成 rm you are my friend.mp3 (共四個參數,但我們需要把它變成一個) $rm "$file" 修正:把 $file 加上雙引號就可以了
  8. 8. 變數 (VARIABLE) 8 類型 指令 說明 陣列 declare -a variable 字串陣列 組合陣列 declare -A variable 可用字串當索引的陣列 整數 declare -i variable 整數變數 只能讀取 declare -r variable=value 只能讀取的變數,無法修改 匯出 declare -x variable 可以匯出到子程序的變數
  9. 9. 參數擴展 (PARAMETER EXPANSION) 9 $echo "$USER, $USERs, ${USER}s" coming, , comings 使用參數擴展時,可以利用大括號限設參數名稱
  10. 10. 特別變數 10 變數 使用方式 說明 0 $0 執行的腳本名稱 1..N $1 執行腳本時,所輸入的第 1 (N) 個參數 # $# 參數的個數 * $* 把所有的參數整理成一個字串 @ $@ 把所有的參數整理成一個陣列 ? $? 上一個前景指令的執行反回值 $ $$ 目前 shell 的程序識別碼 ! $! 上一次執行的背景指令程序識別碼 _ $_ 上一次執行的指令所帶的最後一個參數
  11. 11. 特別變數範例 11 echo "$0 = $0" echo "$1 = $1" echo "$2 = $2" echo "$# = $#" echo "$* = $*" echo "$@ = $@" echo "$? = $?" echo "$$ = $$" echo "$! = $!" echo "$_ = $_"
  12. 12. 特別變數範例 12 $ if.sh para1 para2 $0 = /media/sf_share/if.sh $1 = para1 $2 = para2 $# = 2 $* = para1 para2 $@ = para1 para2 $? = 0 $$ = 2076 $! = $_ = $! = 執行結果
  13. 13. 數術運算 13 i=5 ((i=i*4)) ((i=i/2)) ((i=i+2)) ((i=i-2)) ((i--)) ((i++)) 使用 ((...)) 進行數學運算
  14. 14. 使用指令執行結果當參數 14 now=`date` echo "now = $now" now=$(date) echo "now = $now" 可以使用 `COMMAND` 或是 $(COMMAND) ` 是在鍵盤 1 左邊的符號 now = Sun Nov 2 10:26:56 CST 2014 now = Sun Nov 2 10:26:56 CST 2014 執行結果
  15. 15. TEST 指令 15 test Expression [ Expression ] 0: True 1: False $[ 1 = 2 ]; echo $? # $? 為前一個指令的回傳值 1 $[ 1 = 1 ]; echo $? 0 範例 語法
  16. 16. TEST 指令字串判斷 16 $myname='Michael Jackson' yourname='Michael Jordan' $[ $myname = $yourname ] -bash: [: too many arguments $myname='Michael Jackson' yourname='Michael Jordan' $[ Michael Jackson = Michael Jordon ] -bash: [: too many arguments 實際的執行狀況,參數被展開了,但沒用雙引號括起來 $myname='Michael Jackson' yourname='Michael Jordan' $[ "$myname" = "$yourname" ] $[[ $myname = $yourname ]] 修正:加上雙引號,或是改使用 [[ 與 ]]
  17. 17. TEST 指令檔案判斷 17 指令 說明 -e FILE 判斷 FILE 是否存在 -f FILE 判斷 FILE是否存在且為檔案(file)? -d FILE 判斷 FILE是否存在且為目錄(directory)? -h FILE 判斷 FILE是為符號式連結 -p FILE 判斷 FILE是否存在且為一個 FIFO (pipe) 檔案? -r FILE 判斷 FILE是否存在且具有『可讀』的權限? -s FILE 判斷 FILE是否存在且為『非空白檔案』? -w FILE 判斷 FILE是否存在且具有『可寫』的權限? -x FILE 判斷 FILE是否存在且具有『可執行』的權限?
  18. 18. TEST 指令檔案判斷 18 指令 說明 -O FILE 判斷 FILE的擁有者是否為執行腳本的使用者 -G FILE 判斷 FILE的擁有者是否為執行腳本的使用者的所屬群組 FILE1 -nt FILE2 判斷 FILE1 是否比 FILE2 還新 FILE1 -ot FILE2 判斷 FILE1 是否比 FILE2 還舊
  19. 19. TEST 指令字串判斷 19 指令 說明 -z STR 判斷 STR 的長度是否為 0 -n STR 判斷 STR 的長度是否不為 0 STR1 = STR2 判斷 STR1 是否與 STR2 相同 STR1 != STR2 判斷 STR1 是否與 STR2 不相同 STR1 < STR2 判斷 STR1 在排序時,是否排在 STR2 後面 STR1 > STR2 判斷 STR1 在排序時,是否排在 STR2 前面
  20. 20. TEST 指令整數判斷 20 指令 說明 INT1 -eq INT2 INT1 是否等於 INT2 (=) INT1 -ne INT2 INT1 是否不等於 INT2 (!=) INT1 -lt INT2 INT1 是否小於 INT2 (<) INT1 -gt INT2 INT1 是否大於 INT2 (>) INT1 -le INT2 INT1 是否小於或等於 INT2 (<=) INT1 -ge INT2 INT1 是否大於或等於 INT2 (>=) 注意, >, <, = 是給字串用的
  21. 21. TEST 指令其它判斷 21 指令 說明 EXPR1 -a EXPR2 當 EXPR1 與 EXPR2 皆為 True 時,則為 True EXPR1 -o EXPR2 當 EXPR1 或 EXPR2 為 True 時,則為 True !EXPR NOT 運算,當 EXPR 為 False 時則為 True
  22. 22. [[ 額外的判斷 22 指令 說明 STR = (或 ==) PATTERN 比對 STR 是否符合 glob pattern STR =~ REGEX 比對 STR 是否符合 REGEX EXPR1 && EXPR2 與 [ -a 相同,但是當 EXPR1 為 True 時, 才會推算 EXPR2 EXPR1 || EXPR2 與 [ -o 相同,但是當 EXPR1 為 True 時, 才不會推算 EXPR2 (EXPR) 改變推算的順序
  23. 23. GLOB 樣版 (GLOB PATTERN) 23 樣版 說明 * 符合任何字串,包含空字串 ? 符合任何單一字元 [...] 符合任何在括號內的字元 $ echo * # 顯示在目前目錄下,所有的目錄及檔案(如果有的話) $ touch a.txt b.txt c.txt aa.txt $ echo ?.txt # 顯示在目前目錄下,只包含一個字元的 txt 檔 a.txt b.txt c.txt $ echo [ab].txt # 顯示在目前目錄下,以a或b為檔名的 txt 檔 a.txt b.txt $ echo [ab]?.txt # 顯示在目前目錄下,以a或b為開頭,二個字元為檔名 a.txt b.txt # 的 txt 檔
  24. 24. IF 條件式判斷 24 if COMMANDS # 透過 COMMAND 的執行結果來判斷 TRUE/FALSE, $? then OTHER COMMANDS fi if COMMANDS then OTHER COMMANDS fi if COMMANDS; then OTHER COMMANDS fi if [ 1 –gt 2] # 實際上,就是執行 test 指令,所以要注意空格 then echo "True" fi 語法 範例
  25. 25. IF ELSE 條件式判斷 25 if COMMANDS then OTHER COMMANDS else OTHER COMMANDS fi if [ a = b ] # 實際上,就是執行 test 指令,所以要注意空格 then echo "True" else echo "False" fi 語法 範例
  26. 26. IF ELIF ELSE 條件式判斷 26 if COMMANDS; then OTHER COMMANDS elif COMMAND; then OTHER COMMANDS else OTHER COMMANDS fi if [ 1 = 2 ]; then echo "1 == 2" elif [ 1 = 3 ]; then echo "1 == 3" else echo "1 != 2 and 1 != 3" fi 範例 語法
  27. 27. IF 範例 27 # 判斷 a.txt 是否存在 if [ -e a.txt ]; then echo "a.txt exists" else echo "a.txt doesn't exist" fi # 判斷 tmp 是否為目錄 if [ -d tmp ]; then echo "tmp is a directory" else echo "tmp isn't a directory " fi a.txt exists tmp isn't a directory 輸出
  28. 28. IF 範例-使用 AND 運算 28 if [ 1 = 1 ] && [ 2 = 2 ]; then echo "true" else echo "false" fi if [ 1 = 1 -a 2 = 2 ]; then echo "true" else echo "false" fi
  29. 29. IF 範例-使用 OR 運算 29 if [ 1 = 1 ] || [ 2 = 2 ]; then echo "true" else echo "false" fi if [ 1 = 1 -o 2 = 2 ]; then echo "true" else echo "false" fi
  30. 30. IF 範例-使用 NOT 運算 30 if [ ! 1 = 1 ]; then # 在 [ 後加上 ! 就行了 echo "true" else echo "false" fi
  31. 31. IF 範例-實作加減法 31 if [ ! $# -eq 3 ]; then echo "${0} param1 [+|-] param2" echo "e.g. " echo "${0} param1 + param2" echo "${0} param1 - param2" exit fi if [ $2 == '+' ]; then echo "result = $(($1+$3))" elif [ $2 = '-' ]; then echo "result = $(($1-$3))" else echo "unknown operation: $2" fi $add.sh 1 - 6 result = -5 $add.sh 1 + 6 result = 7 輸出
  32. 32. IF 範例-巢狀結構 32 if [ $1 -gt 20 ]; then if [ $1 -gt 25 ]; then echo "$1 > 25" else echo "20 < $1 <= 25" fi elif [ $1 -gt 10 ]; then if [ $1 -gt 15 ]; then echo "15 < $1 <= 20" else echo "10 < $1 <= 15" fi else echo "$1 <= 10" fi $./exam.sh 6 6 <= 10 $./exam.sh 11 10 < 11 <= 15 $./exam.sh 16 15 < 16 <= 20 $./exam.sh 21 20 < 21 <= 25 $./exam.sh 26 26 > 25 輸出
  33. 33. WHILE 迴圈 33 while COMMAND; do OTHER COMMANDs done while COMMAND do OTHER COMMANDs done while COMMAND do OTHER COMMANDs done
  34. 34. WHILE 迴圈範例 34 while ! ping -c 1 -W 1 1.2.3.4 do echo "still waiting for 1.2.3.4" sleep 1 done while true do echo "Infinite loop" done 無窮回圈 不斷地 ping 1.2.3.4 直到成功為止
  35. 35. WHILE 迴圈範例 35 (( i=10 )); # 透過 (( )) 進行算術運算 while (( i > 0 )) do echo "i = $i" (( i-- )) done 從 i = 10..1, 輸出 i = 10 到 i = 1
  36. 36. WHILE 迴圈範例 36 i=1 result=0 while((i<50)) do ((result=result+i)) ((i=i+1)) done echo $result 計算 1+2+3...+50 的結果
  37. 37. WHILE 範例-讀取檔案 37 N=0 # 行號變數 while read line # 透過 read 指令,從標準輸入讀入一行到變數 line do ((N=N+1)) # 行號累加 echo "$N: $line" done < $1 # 把 $1 檔案導到 while 指令的標準輸入 使用 read 指令及標準輸入的重新導向讀取檔案
  38. 38. 範例資料檔 38 Jim Lin,4,41 Tim Lee,8,12 Johnson Lin,6,20 Tom Wang,1,31 Esko Huang,2,51 Jaska Lu,5,19 Erkk Zhuang,7,9
  39. 39. WHILE 範例-讀取檔案資料 39 while read line # 透過 read 指令,從標準輸入讀入一行到變數 line do IFS=',' # 設定分隔符號為 , read -a record <<< "$line" # 以 , 為分隔符號, # 把 $line 的字串讀入陣列 record echo ${record[0]} echo ${record[1]} echo ${record[2]} done < $1 # 把 $1 檔案導到 while 指令的標準輸入
  40. 40. FOR 迴圈 40 for variable in {n..N}; do COMMANDs done for i in {10..1}; do echo $i done for i in {1..10}; do echo $i done 語法1 整數變數 範例
  41. 41. FOR 迴圈 41 for variable in str1 str2 ... strn; do COMMANDs done for i in a b c; do echo $i done str="a b c" for i in $str; do echo $i done 語法2 字串陣列 範例 a b c 輸出
  42. 42. FOR 迴圈 42 str="a b c" for i in "$str"; do # 輸入的參數變成 "a b c" 而不是 a b c echo $i done a b c 輸出 字串陣列加上雙引號會變回單一字串
  43. 43. FOR 迴圈-腳本參數處理 43 for i in $* do echo $i done $@ 不加雙引號 for i in "$*" do echo $i done $@ 加雙引號 $./exam.sh a a b a a b $./exam.sh a a b a a b 輸出 輸出
  44. 44. FOR 迴圈-腳本參數處理 44 for i in $@ do echo $i done $@ 不加雙引號 for i in "$@" do echo $i done $@ 加雙引號 $./exam.sh a a b a a b $./exam.sh a a b a a b 輸出 輸出
  45. 45. FOR 迴圈 45 for i in *; do # 使用 glob pattern * echo $i done course Desktop Documents Downloads examples.desktop Music Pictures Public Templates tmp Videos 輸出 利用 for loop 及 Glob Pattern 輸出目前目錄下所有的檔案及目錄
  46. 46. FOR 迴圈 46 for i in *.txt; do # 使用 glob pattern * echo $i done $touch a.txt b.txt a.sh b.sh $./exam.sh a.txt b.txt 輸出 輸出以 txt 為副檔名的檔案
  47. 47. FOR 迴圈-讀檔 47 for line in $(cat $1) do echo "$line" done $./exam.sh exam.sh #!/bin/bash for line in $(cat $1) do echo "$line" done 輸出: 不是以行為單位輸出
  48. 48. FOR 迴圈-讀檔(修正) 48 IFS=$'n' # 設定分隔符號為 n for line in $(cat $1) do echo "$line" done $./exam.sh exam.sh #!/bin/bash IFS=$'n' for line in $(cat $1) do echo "$line" done 輸出: 以行為單位輸出
  49. 49. BREAK 與 CONTINUE  break  中斷目前迴圈執行  continue  中止目前的執行,改執行迴圈的下一次執行 49
  50. 50. BREAK 與 CONTINUE 50 for i in {1..5} do if [ $i == 2 ]; then continue; # 碰到 2 則直接執行迴圈的下一次執行 elif [ $i == 4 ]; then break; # 碰到 4 執直接離開迴圈 fi echo $i done $./exam.sh 1 3 輸出: 2 被跳過,迴圈執行 4 就中止,沒有執行到 5
  51. 51. SWITCH 51 case expression in pattern1 ) statements ;; pattern2 ) statements ;; ... esac
  52. 52. SWITCH 範例 52 case expression in pattern1 ) statements ;; pattern2 ) statements ;; ... esac
  53. 53. SWITCH 範例 字串的比較 53 case "$1" in george) echo "Hello George!";; mary) echo "Good morning Mary";; *) echo "Who are you, $1?";; esac $./exam.sh mary Good morning Mary $./exam.sh george Hello George! $./exam.sh jonh Who are you, jonh? 輸出
  54. 54. SWITCH 範例 數字的比較 54 case "$1" in 1) echo "This is No.1";; 2) echo "This is No.2";; *) echo ""Unkonwn number $1";; esac $./exam.sh 1 This is No.1 $./exam.sh 2 This is No.2 $./exam.sh 3 Unkonwn number 3 輸出
  55. 55. SELECT 選擇迴圈 55 select variable in str1 str2 ... strn; do COMMANDs done
  56. 56. SELECT 選擇迴圈範例-選擇檔案 56 select filename in *; do echo "you pick $filename $REPLY " break # 要透過 break 中止 select 迴圈的執行,不然會一直詢問 done $./exam.sh 1) a.sh 3) b.sh 5) exam.sh 7) score.txt 2) a.txt 4) b.txt 6) if.sh #? 3 you pick b.sh 3 輸出
  57. 57. SELECT 選擇迴圈範例-選擇顏色 57 select color in red green blue; do case $color in "$quit") echo "bye" break # 透過 break 指令離開 selec 迴圈 ;; *) echo "you pick $color color $REPLY" ;; esac done 選擇 red/green/blue 三種顏色,或是輸入 quit 離開
  58. 58. SELECT 選擇迴圈範例-選擇顏色 58 輸出 $./exam.sh 1) red 2) green 3) blue #? 1 you pick red color 1 #? 2 you pick green color 2 #? 3 you pick blue color 3 #? quit bye
  59. 59. 函式 (FUNCTION) 59 function FunctionName { COMMANDS } FunctionName () { COMMANDS } 語法1: 使用 function 關鍵字宣告 語法2: 不使用 function 關鍵字宣告,但需加入 ()
  60. 60. 函式 (FUNCTION) 60 hello () { echo -e "hello, $1 = $1, $2 = $2n" } hello 1 2 # 執行函式 $./exam.sh hello, $1 = 1, $2 = 2 輸出
  61. 61. 函式回傳值 61 is_equal_to () { if [ $1 -eq $2 ]; then return 0 fi return 1 } is_equal_to 1 2 echo $? is_equal_to 1 1 echo $? $./exam.sh 1 0 輸出
  62. 62. 離開執行 (EXIT) 62 exit_func () { if [ $1 = 1 ]; then echo "exit in func" exit 1 fi } exit_func $1 echo "exit in main" exit 0 $./exam.sh 0; echo $? exit in main 0 $./exam.sh 1; echo $? exit in func 輸出
  63. 63. 全域及區域變數 63 global_var="global value" # 宣告 local_var 變數 echo "$local_var = $local_var" # 尚未有 local_var 變數 func1 () { local_var="func1" global_var="func1" echo "$local_var = $local_var" echo "$global_var = $global_var" } func2 () { local_var="func2" global_var="func2" echo "$local_var = $local_var" echo "$global_var = $global_var" } echo "execute func1" func1 echo "execute func2" func2 echo "back to main" echo "$local_var = $local_var" echo "$global_var = $global_var"
  64. 64. 全域及區域變數 64 $./exam.sh $local_var = # local_var 尚未被宣告,所以無值 execute func1 $local_var = func1 $global_var = func1 # global_var 已宣告過 execute func2 $local_var = func2 # local_var 已在 func 1 被宣告 $global_var = func2 back to main $local_var = func2 # 皆為 func2 修改過後的結果 $global_var = func2 輸出
  65. 65. 全域及區域變數-使用 LOCAL 65 VAR="global" func() { echo $VAR local VAR="local" echo $VAR } func echo $VAR 使用 local 宣告變數後,該變數便只能在函式內使用 $./exam.sh global # 在 func 內讀取的 VAR 值為 global local # 使用 local 宣告 VAR 變數後,VAR 成區域變數 global # 離開 func 後,VAR 變回全域變數 輸出
  66. 66. 匯出參數 66 export VAR=$1 $./exam.sh 11; echo $VAR # 執行完後,腳本內的 VAR 參數即消失 $source ./exam.sh 11; echo $VAR 11 # 使用 source 指令, 腳本內參數會保留 $. ./exam.sh 22; echo $VAR # 也可以用 . 來執行 22 輸出
  67. 67. 輸出重導 67 File Descriptor 說明 1 (預設) 標準輸出 (stdout) 2 標準錯誤輸出 (stderr) & (在 > 前時) 包含標準輸出及標準錯誤輸出 &<fd>(在 < 後時) 表示重導至 <fd> $ ls -l >stdout.txt # 把輸出結果寫到 stdout.txt $ ls -l /root >stderr.txt # 沒權限讀取 /root 目錄, # 標準錯誤輸出到 stderr.txt $ ls -l &>all.txt # 把標準輸出及標準錯誤輸出寫到 all.txt $ ls -l 1>&2 # 把標準輸出導至標準錯誤輸出
  68. 68. SHIFT 68 while (( "$#" )) do echo "$1 = $1, $@ = $@" shift done $./exam.sh 1 2 3 $1 = 1, $@ = 1 2 3 $1 = 2, $@ = 2 3 $1 = 3, $@ = 3 輸出 使用 shift 指令來左移輸入的參數

×