68
BASH SHELL SCRIPT 教學 1

Bash shell script 教學

  • Upload
    -

  • View
    824

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Bash shell script 教學

BASH SHELL SCRIPT教學1

Page 2: Bash shell script 教學

建立第一個 HELLO WORLD腳本 (SCRIPT)

#!/bin/bash

echo "hello world"

儲存成 hello.sh

2

Page 3: Bash shell script 教學

執行腳本

$chmod +x hello.sh

$./hello.sh

或者

$bash hello.sh

3

Page 4: Bash shell script 教學

指令與參數 (COMMAND AND ARGUMENT)

bash 會依照空格本分辨指令及參數

指令 參數1 參數2 … 參數n

$touch a b c

$touch a b c # 即使超過一個空格也沒問題

4

Page 5: Bash shell script 教學

指令與參數

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

Page 6: Bash shell script 教學

參數的設定

$var=abc O

$var = abc X

$var =abc X

6

變數與 = 之間不能有空白,有空白會被當成指令的參數

Page 7: Bash shell script 教學

參數的使用

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 加上雙引號就可以了

Page 8: Bash shell script 教學

變數 (VARIABLE)

8

類型 指令 說明

陣列 declare -a variable 字串陣列

組合陣列 declare -A variable 可用字串當索引的陣列

整數 declare -i variable 整數變數

只能讀取 declare -r variable=value 只能讀取的變數,無法修改

匯出 declare -x variable 可以匯出到子程序的變數

Page 9: Bash shell script 教學

參數擴展 (PARAMETER EXPANSION)

9

$echo "$USER, $USERs, ${USER}s"

coming, , comings

使用參數擴展時,可以利用大括號限設參數名稱

Page 10: Bash shell script 教學

特別變數

10

變數 使用方式 說明

0 $0 執行的腳本名稱

1..N $1 執行腳本時,所輸入的第 1 (N) 個參數

# $# 參數的個數

* $* 把所有的參數整理成一個字串

@ $@ 把所有的參數整理成一個陣列

? $? 上一個前景指令的執行反回值

$ $$ 目前 shell 的程序識別碼

! $! 上一次執行的背景指令程序識別碼

_ $_ 上一次執行的指令所帶的最後一個參數

Page 11: Bash shell script 教學

特別變數範例

11

echo "\$0 = $0"

echo "\$1 = $1"

echo "\$2 = $2"

echo "\$# = $#"

echo "\$* = $*"

echo "\$@ = $@"

echo "\$? = $?"

echo "\$$ = $$"

echo "\$! = $!"

echo "\$_ = $_"

Page 12: Bash shell script 教學

特別變數範例

12

$ if.sh para1 para2

$0 = /media/sf_share/if.sh

$1 = para1

$2 = para2

$# = 2

$* = para1 para2

$@ = para1 para2

$? = 0

$$ = 2076

$! =

$_ = $! =

執行結果

Page 13: Bash shell script 教學

數術運算

13

i=5

((i=i*4))

((i=i/2))

((i=i+2))

((i=i-2))

((i--))

((i++))

使用 ((...)) 進行數學運算

Page 14: Bash shell script 教學

使用指令執行結果當參數

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

執行結果

Page 15: Bash shell script 教學

TEST指令

15

test Expression[ Expression ]

0: True1: False

$[ 1 = 2 ]; echo $? # $? 為前一個指令的回傳值1$[ 1 = 1 ]; echo $?0

範例

語法

Page 16: Bash shell script 教學

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 ]]

修正:加上雙引號,或是改使用 [[ 與 ]]

Page 17: Bash shell script 教學

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是否存在且具有『可執行』的權限?

Page 18: Bash shell script 教學

TEST指令檔案判斷

18

指令 說明

-O FILE 判斷 FILE的擁有者是否為執行腳本的使用者

-G FILE 判斷 FILE的擁有者是否為執行腳本的使用者的所屬群組

FILE1 -nt FILE2 判斷 FILE1是否比 FILE2還新

FILE1 -ot FILE2 判斷 FILE1是否比 FILE2還舊

Page 19: Bash shell script 教學

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前面

Page 20: Bash shell script 教學

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 (>=)

注意, >, <, = 是給字串用的

Page 21: Bash shell script 教學

TEST指令其它判斷

21

指令 說明

EXPR1 -a EXPR2 當 EXPR1與 EXPR2皆為 True 時,則為 True

EXPR1 -o EXPR2 當 EXPR1或 EXPR2為 True 時,則為 True

!EXPR NOT運算,當 EXPR為 False 時則為 True

Page 22: Bash shell script 教學

[[ 額外的判斷

22

指令 說明

STR = (或 ==) PATTERN 比對 STR是否符合 glob pattern

STR =~ REGEX 比對 STR是否符合 REGEX

EXPR1 && EXPR2 與 [ -a 相同,但是當 EXPR1為 True時,才會推算 EXPR2

EXPR1 || EXPR2 與 [ -o 相同,但是當 EXPR1為 True時,才不會推算 EXPR2

(EXPR) 改變推算的順序

Page 23: Bash shell script 教學

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 檔

Page 24: Bash shell script 教學

IF條件式判斷

24

if COMMANDS # 透過 COMMAND 的執行結果來判斷 TRUE/FALSE, $?then OTHER COMMANDSfi

if COMMANDSthen

OTHER COMMANDSfi

if COMMANDS; thenOTHER COMMANDS

fi

if [ 1 –gt 2] # 實際上,就是執行 test 指令,所以要注意空格then echo "True"fi

語法

範例

Page 25: Bash shell script 教學

IF ELSE條件式判斷

25

if COMMANDSthen OTHER COMMANDSelse OTHER COMMANDSfi

if [ a = b ] # 實際上,就是執行 test 指令,所以要注意空格then echo "True"else echo "False"fi

語法

範例

Page 26: Bash shell script 教學

IF ELIF ELSE條件式判斷

26

if COMMANDS; thenOTHER COMMANDS

elif COMMAND; thenOTHER COMMANDS

else OTHER COMMANDSfi

if [ 1 = 2 ]; thenecho "1 == 2"

elif [ 1 = 3 ]; thenecho "1 == 3"

elseecho "1 != 2 and 1 != 3"

fi

範例

語法

Page 27: Bash shell script 教學

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 existstmp isn't a directory

輸出

Page 28: Bash shell script 教學

IF 範例-使用 AND 運算

28

if [ 1 = 1 ] && [ 2 = 2 ]; thenecho "true"

elseecho "false"

fi

if [ 1 = 1 -a 2 = 2 ]; thenecho "true"

elseecho "false"

fi

Page 29: Bash shell script 教學

IF 範例-使用 OR 運算

29

if [ 1 = 1 ] || [ 2 = 2 ]; thenecho "true"

elseecho "false"

fi

if [ 1 = 1 -o 2 = 2 ]; thenecho "true"

elseecho "false"

fi

Page 30: Bash shell script 教學

IF 範例-使用 NOT 運算

30

if [ ! 1 = 1 ]; then # 在 [ 後加上 ! 就行了echo "true"

elseecho "false"

fi

Page 31: Bash shell script 教學

IF 範例-實作加減法

31

if [ ! $# -eq 3 ]; thenecho "${0} param1 [+|-] param2"echo "e.g. "echo "${0} param1 + param2"echo "${0} param1 - param2"exit

fi

if [ $2 == '+' ]; thenecho "result = $(($1+$3))"

elif [ $2 = '-' ]; thenecho "result = $(($1-$3))"

elseecho "unknown operation: $2"

fi

$add.sh 1 - 6result = -5$add.sh 1 + 6result = 7

輸出

Page 32: Bash shell script 教學

IF 範例-巢狀結構

32

if [ $1 -gt 20 ]; thenif [ $1 -gt 25 ]; then

echo "$1 > 25"else

echo "20 < $1 <= 25"fi

elif [ $1 -gt 10 ]; thenif [ $1 -gt 15 ]; then

echo "15 < $1 <= 20"else

echo "10 < $1 <= 15"fi

elseecho "$1 <= 10"

fi

$./exam.sh 66 <= 10$./exam.sh 1110 < 11 <= 15$./exam.sh 1615 < 16 <= 20$./exam.sh 2120 < 21 <= 25$./exam.sh 2626 > 25

輸出

Page 33: Bash shell script 教學

WHILE迴圈

33

while COMMAND; doOTHER COMMANDs

done

while COMMANDdo OTHER COMMANDsdone

while COMMANDdo

OTHER COMMANDsdone

Page 34: Bash shell script 教學

WHILE迴圈範例

34

while ! ping -c 1 -W 1 1.2.3.4do

echo "still waiting for 1.2.3.4"sleep 1

done

while truedo

echo "Infinite loop"done

無窮回圈

不斷地 ping 1.2.3.4 直到成功為止

Page 35: Bash shell script 教學

WHILE迴圈範例

35

(( i=10 )); # 透過 (( )) 進行算術運算while (( i > 0 ))do

echo "i = $i"(( i-- ))

done

從 i = 10..1, 輸出 i = 10 到 i = 1

Page 36: Bash shell script 教學

WHILE迴圈範例

36

i=1result=0while((i<50))do

((result=result+i))((i=i+1))

done

echo $result

計算 1+2+3...+50 的結果

Page 37: Bash shell script 教學

WHILE範例-讀取檔案

37

N=0 # 行號變數while read line # 透過 read 指令,從標準輸入讀入一行到變數 linedo

((N=N+1)) # 行號累加echo "$N: $line"

done < $1 # 把 $1 檔案導到 while 指令的標準輸入

使用 read 指令及標準輸入的重新導向讀取檔案

Page 38: Bash shell script 教學

範例資料檔

38

Jim Lin,4,41Tim Lee,8,12Johnson Lin,6,20Tom Wang,1,31Esko Huang,2,51Jaska Lu,5,19Erkk Zhuang,7,9

Page 39: Bash shell script 教學

WHILE範例-讀取檔案資料

39

while read line # 透過 read 指令,從標準輸入讀入一行到變數 linedo

IFS=',' # 設定分隔符號為 ,read -a record <<< "$line" # 以 , 為分隔符號,

# 把 $line 的字串讀入陣列 recordecho ${record[0]}echo ${record[1]}echo ${record[2]}

done < $1 # 把 $1 檔案導到 while 指令的標準輸入

Page 40: Bash shell script 教學

FOR迴圈

40

for variable in {n..N}; doCOMMANDs

done

for i in {10..1}; do echo $i

done

for i in {1..10}; do echo $i

done

語法1 整數變數

範例

Page 41: Bash shell script 教學

FOR迴圈

41

for variable in str1 str2 ... strn; doCOMMANDs

done

for i in a b c; do echo $i

done

str="a b c"for i in $str; do

echo $idone

語法2 字串陣列

範例

a b c

輸出

Page 42: Bash shell script 教學

FOR迴圈

42

str="a b c"for i in "$str"; do # 輸入的參數變成 "a b c" 而不是 a b c

echo $idone

a b c

輸出

字串陣列加上雙引號會變回單一字串

Page 43: Bash shell script 教學

FOR迴圈-腳本參數處理

43

for i in $*do

echo $idone

$@ 不加雙引號

for i in "$*"do

echo $idone

$@ 加雙引號

$./exam.sh a a\ baab

$./exam.sh a a\ ba a b

輸出

輸出

Page 44: Bash shell script 教學

FOR迴圈-腳本參數處理

44

for i in $@do

echo $idone

$@ 不加雙引號

for i in "$@"do

echo $idone

$@ 加雙引號

$./exam.sh a a\ baab

$./exam.sh a a\ ba a b

輸出

輸出

Page 45: Bash shell script 教學

FOR迴圈

45

for i in *; do # 使用 glob pattern *echo $i

done

courseDesktopDocumentsDownloadsexamples.desktopMusicPicturesPublicTemplatestmpVideos

輸出

利用 for loop 及 Glob Pattern 輸出目前目錄下所有的檔案及目錄

Page 46: Bash shell script 教學

FOR迴圈

46

for i in *.txt; do # 使用 glob pattern *echo $i

done

$touch a.txt b.txt a.sh b.sh$./exam.sha.txtb.txt

輸出

輸出以 txt 為副檔名的檔案

Page 47: Bash shell script 教學

FOR迴圈-讀檔

47

for line in $(cat $1)do

echo "$line" done

$./exam.sh exam.sh#!/bin/bashforlinein$(cat$1)doecho"$line"done

輸出: 不是以行為單位輸出

Page 48: Bash shell script 教學

FOR迴圈-讀檔(修正)

48

IFS=$'\n' # 設定分隔符號為 \n for line in $(cat $1)do

echo "$line" done

$./exam.sh exam.sh#!/bin/bashIFS=$'\n'for line in $(cat $1)do

echo "$line"done

輸出: 以行為單位輸出

Page 49: Bash shell script 教學

BREAK 與 CONTINUE

break

中斷目前迴圈執行

continue

中止目前的執行,改執行迴圈的下一次執行

49

Page 50: Bash shell script 教學

BREAK 與 CONTINUE

50

for i in {1..5}do

if [ $i == 2 ]; thencontinue; # 碰到 2 則直接執行迴圈的下一次執行

elif [ $i == 4 ]; thenbreak; # 碰到 4 執直接離開迴圈

fiecho $i

done

$./exam.sh13

輸出: 2 被跳過,迴圈執行 4 就中止,沒有執行到 5

Page 51: Bash shell script 教學

SWITCH

51

case expression inpattern1 ) statements ;; pattern2 ) statements ;; ...

esac

Page 52: Bash shell script 教學

SWITCH範例

52

case expression inpattern1 ) statements ;; pattern2 ) statements ;; ...

esac

Page 53: Bash shell script 教學

SWITCH範例 字串的比較

53

case "$1" ingeorge)

echo "Hello George!";;mary)

echo "Good morning Mary";;*)

echo "Who are you, $1?";;esac

$./exam.sh maryGood morning Mary$./exam.sh georgeHello George!$./exam.sh jonhWho are you, jonh?

輸出

Page 54: Bash shell script 教學

SWITCH範例 數字的比較

54

case "$1" in1)

echo "This is No.1";;2)

echo "This is No.2";;*)

echo ""Unkonwn number $1";;esac

$./exam.sh 1This is No.1$./exam.sh 2This is No.2$./exam.sh 3Unkonwn number 3

輸出

Page 55: Bash shell script 教學

SELECT選擇迴圈

55

select variable in str1 str2 ... strn; do

COMMANDsdone

Page 56: Bash shell script 教學

SELECT選擇迴圈範例-選擇檔案

56

select filename in *;do

echo "you pick $filename $REPLY "break # 要透過 break 中止 select 迴圈的執行,不然會一直詢問

done

$./exam.sh1) a.sh 3) b.sh 5) exam.sh 7) score.txt2) a.txt 4) b.txt 6) if.sh#? 3you pick b.sh 3

輸出

Page 57: Bash shell script 教學

SELECT選擇迴圈範例-選擇顏色

57

select color in red green blue;do

case $color in"$quit")

echo "bye"break # 透過 break 指令離開 selec 迴圈;;

*)echo "you pick $color color $REPLY";;

esacdone

選擇 red/green/blue 三種顏色,或是輸入 quit 離開

Page 58: Bash shell script 教學

SELECT選擇迴圈範例-選擇顏色

58

輸出

$./exam.sh1) red2) green3) blue#? 1you pick red color 1#? 2you pick green color 2#? 3you pick blue color 3#? quitbye

Page 59: Bash shell script 教學

函式 (FUNCTION)

59

function FunctionName{

COMMANDS}

FunctionName (){

COMMANDS}

語法1: 使用 function 關鍵字宣告

語法2: 不使用 function 關鍵字宣告,但需加入 ()

Page 60: Bash shell script 教學

函式 (FUNCTION)

60

hello (){

echo -e "hello, \$1 = $1, \$2 = $2\n" }

hello 1 2 # 執行函式

$./exam.shhello, $1 = 1, $2 = 2

輸出

Page 61: Bash shell script 教學

函式回傳值

61

is_equal_to (){

if [ $1 -eq $2 ]; thenreturn 0

fi

return 1}

is_equal_to 1 2echo $?

is_equal_to 1 1echo $?

$./exam.sh10

輸出

Page 62: Bash shell script 教學

離開執行 (EXIT)

62

exit_func (){

if [ $1 = 1 ]; thenecho "exit in func"exit 1

fi}

exit_func $1echo "exit in main"exit 0

$./exam.sh 0; echo $?exit in main0$./exam.sh 1; echo $?exit in func

輸出

Page 63: Bash shell script 教學

全域及區域變數

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"func1echo "execute func2"func2echo "back to main"echo "\$local_var = $local_var" echo "\$global_var = $global_var"

Page 64: Bash shell script 教學

全域及區域變數

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 = func2back to main$local_var = func2 # 皆為 func2 修改過後的結果$global_var = func2

輸出

Page 65: Bash shell script 教學

全域及區域變數-使用 LOCAL

65

VAR="global"func(){

echo $VARlocal VAR="local"echo $VAR

}

funcecho $VAR

使用 local 宣告變數後,該變數便只能在函式內使用

$./exam.shglobal # 在 func 內讀取的 VAR 值為 globallocal # 使用 local 宣告 VAR 變數後,VAR 成區域變數global # 離開 func 後,VAR 變回全域變數

輸出

Page 66: Bash shell script 教學

匯出參數

66

export VAR=$1

$./exam.sh 11; echo $VAR# 執行完後,腳本內的 VAR 參數即消失

$source ./exam.sh 11; echo $VAR11 # 使用 source 指令, 腳本內參數會保留$. ./exam.sh 22; echo $VAR # 也可以用 . 來執行22

輸出

Page 67: Bash shell script 教學

輸出重導

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 # 把標準輸出導至標準錯誤輸出

Page 68: Bash shell script 教學

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 指令來左移輸入的參數