Upload
-
View
824
Download
1
Embed Size (px)
Citation preview
BASH SHELL SCRIPT教學1
建立第一個 HELLO WORLD腳本 (SCRIPT)
#!/bin/bash
echo "hello world"
儲存成 hello.sh
2
執行腳本
$chmod +x hello.sh
$./hello.sh
或者
$bash hello.sh
3
指令與參數 (COMMAND AND ARGUMENT)
bash 會依照空格本分辨指令及參數
指令 參數1 參數2 … 參數n
$touch a b c
$touch a b c # 即使超過一個空格也沒問題
4
指令與參數
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
參數的設定
$var=abc O
$var = abc X
$var =abc X
6
變數與 = 之間不能有空白,有空白會被當成指令的參數
參數的使用
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 加上雙引號就可以了
變數 (VARIABLE)
8
類型 指令 說明
陣列 declare -a variable 字串陣列
組合陣列 declare -A variable 可用字串當索引的陣列
整數 declare -i variable 整數變數
只能讀取 declare -r variable=value 只能讀取的變數,無法修改
匯出 declare -x variable 可以匯出到子程序的變數
參數擴展 (PARAMETER EXPANSION)
9
$echo "$USER, $USERs, ${USER}s"
coming, , comings
使用參數擴展時,可以利用大括號限設參數名稱
特別變數
10
變數 使用方式 說明
0 $0 執行的腳本名稱
1..N $1 執行腳本時,所輸入的第 1 (N) 個參數
# $# 參數的個數
* $* 把所有的參數整理成一個字串
@ $@ 把所有的參數整理成一個陣列
? $? 上一個前景指令的執行反回值
$ $$ 目前 shell 的程序識別碼
! $! 上一次執行的背景指令程序識別碼
_ $_ 上一次執行的指令所帶的最後一個參數
特別變數範例
11
echo "\$0 = $0"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$# = $#"
echo "\$* = $*"
echo "\$@ = $@"
echo "\$? = $?"
echo "\$$ = $$"
echo "\$! = $!"
echo "\$_ = $_"
特別變數範例
12
$ if.sh para1 para2
$0 = /media/sf_share/if.sh
$1 = para1
$2 = para2
$# = 2
$* = para1 para2
$@ = para1 para2
$? = 0
$$ = 2076
$! =
$_ = $! =
執行結果
數術運算
13
i=5
((i=i*4))
((i=i/2))
((i=i+2))
((i=i-2))
((i--))
((i++))
使用 ((...)) 進行數學運算
使用指令執行結果當參數
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
執行結果
TEST指令
15
test Expression[ Expression ]
0: True1: False
$[ 1 = 2 ]; echo $? # $? 為前一個指令的回傳值1$[ 1 = 1 ]; echo $?0
範例
語法
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 ]]
修正:加上雙引號,或是改使用 [[ 與 ]]
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是否存在且具有『可執行』的權限?
TEST指令檔案判斷
18
指令 說明
-O FILE 判斷 FILE的擁有者是否為執行腳本的使用者
-G FILE 判斷 FILE的擁有者是否為執行腳本的使用者的所屬群組
FILE1 -nt FILE2 判斷 FILE1是否比 FILE2還新
FILE1 -ot FILE2 判斷 FILE1是否比 FILE2還舊
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前面
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 (>=)
注意, >, <, = 是給字串用的
TEST指令其它判斷
21
指令 說明
EXPR1 -a EXPR2 當 EXPR1與 EXPR2皆為 True 時,則為 True
EXPR1 -o EXPR2 當 EXPR1或 EXPR2為 True 時,則為 True
!EXPR NOT運算,當 EXPR為 False 時則為 True
[[ 額外的判斷
22
指令 說明
STR = (或 ==) PATTERN 比對 STR是否符合 glob pattern
STR =~ REGEX 比對 STR是否符合 REGEX
EXPR1 && EXPR2 與 [ -a 相同,但是當 EXPR1為 True時,才會推算 EXPR2
EXPR1 || EXPR2 與 [ -o 相同,但是當 EXPR1為 True時,才不會推算 EXPR2
(EXPR) 改變推算的順序
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 檔
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
語法
範例
IF ELSE條件式判斷
25
if COMMANDSthen OTHER COMMANDSelse OTHER COMMANDSfi
if [ a = b ] # 實際上,就是執行 test 指令,所以要注意空格then echo "True"else echo "False"fi
語法
範例
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
範例
語法
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
輸出
IF 範例-使用 AND 運算
28
if [ 1 = 1 ] && [ 2 = 2 ]; thenecho "true"
elseecho "false"
fi
if [ 1 = 1 -a 2 = 2 ]; thenecho "true"
elseecho "false"
fi
IF 範例-使用 OR 運算
29
if [ 1 = 1 ] || [ 2 = 2 ]; thenecho "true"
elseecho "false"
fi
if [ 1 = 1 -o 2 = 2 ]; thenecho "true"
elseecho "false"
fi
IF 範例-使用 NOT 運算
30
if [ ! 1 = 1 ]; then # 在 [ 後加上 ! 就行了echo "true"
elseecho "false"
fi
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
輸出
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
輸出
WHILE迴圈
33
while COMMAND; doOTHER COMMANDs
done
while COMMANDdo OTHER COMMANDsdone
while COMMANDdo
OTHER COMMANDsdone
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 直到成功為止
WHILE迴圈範例
35
(( i=10 )); # 透過 (( )) 進行算術運算while (( i > 0 ))do
echo "i = $i"(( i-- ))
done
從 i = 10..1, 輸出 i = 10 到 i = 1
WHILE迴圈範例
36
i=1result=0while((i<50))do
((result=result+i))((i=i+1))
done
echo $result
計算 1+2+3...+50 的結果
WHILE範例-讀取檔案
37
N=0 # 行號變數while read line # 透過 read 指令,從標準輸入讀入一行到變數 linedo
((N=N+1)) # 行號累加echo "$N: $line"
done < $1 # 把 $1 檔案導到 while 指令的標準輸入
使用 read 指令及標準輸入的重新導向讀取檔案
範例資料檔
38
Jim Lin,4,41Tim Lee,8,12Johnson Lin,6,20Tom Wang,1,31Esko Huang,2,51Jaska Lu,5,19Erkk Zhuang,7,9
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 指令的標準輸入
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 整數變數
範例
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
輸出
FOR迴圈
42
str="a b c"for i in "$str"; do # 輸入的參數變成 "a b c" 而不是 a b c
echo $idone
a b c
輸出
字串陣列加上雙引號會變回單一字串
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
輸出
輸出
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
輸出
輸出
FOR迴圈
45
for i in *; do # 使用 glob pattern *echo $i
done
courseDesktopDocumentsDownloadsexamples.desktopMusicPicturesPublicTemplatestmpVideos
輸出
利用 for loop 及 Glob Pattern 輸出目前目錄下所有的檔案及目錄
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 為副檔名的檔案
FOR迴圈-讀檔
47
for line in $(cat $1)do
echo "$line" done
$./exam.sh exam.sh#!/bin/bashforlinein$(cat$1)doecho"$line"done
輸出: 不是以行為單位輸出
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
輸出: 以行為單位輸出
BREAK 與 CONTINUE
break
中斷目前迴圈執行
continue
中止目前的執行,改執行迴圈的下一次執行
49
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
SWITCH
51
case expression inpattern1 ) statements ;; pattern2 ) statements ;; ...
esac
SWITCH範例
52
case expression inpattern1 ) statements ;; pattern2 ) statements ;; ...
esac
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?
輸出
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
輸出
SELECT選擇迴圈
55
select variable in str1 str2 ... strn; do
COMMANDsdone
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
輸出
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 離開
SELECT選擇迴圈範例-選擇顏色
58
輸出
$./exam.sh1) red2) green3) blue#? 1you pick red color 1#? 2you pick green color 2#? 3you pick blue color 3#? quitbye
函式 (FUNCTION)
59
function FunctionName{
COMMANDS}
FunctionName (){
COMMANDS}
語法1: 使用 function 關鍵字宣告
語法2: 不使用 function 關鍵字宣告,但需加入 ()
函式 (FUNCTION)
60
hello (){
echo -e "hello, \$1 = $1, \$2 = $2\n" }
hello 1 2 # 執行函式
$./exam.shhello, $1 = 1, $2 = 2
輸出
函式回傳值
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
輸出
離開執行 (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
輸出
全域及區域變數
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"
全域及區域變數
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
輸出
全域及區域變數-使用 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 變回全域變數
輸出
匯出參數
66
export VAR=$1
$./exam.sh 11; echo $VAR# 執行完後,腳本內的 VAR 參數即消失
$source ./exam.sh 11; echo $VAR11 # 使用 source 指令, 腳本內參數會保留$. ./exam.sh 22; echo $VAR # 也可以用 . 來執行22
輸出
輸出重導
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 # 把標準輸出導至標準錯誤輸出
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 指令來左移輸入的參數