如何撰寫Shell Script
如何撰寫Shell Script
前言
Shell 是一種讓使用者可以和作業系統 Kernel(核心用來控制 CPU、記憶體、硬碟等硬體)互動溝通的橋樑。Shell Script 主要是使用在 Linux 和 MacOS 等 Unix-like 作業系統的自動化操作指令的程式語言。其透過 Shell 命令列直譯器來執行(我們這邊主要使用 bash shell,其他的 Unix shell 觀念大致類似)。
一般情況 Shell Script 常用於系統管理、自動化操作檔案、自動化重複的指令碼、分析 log 等文件檔案、列印呈現我們想要的資料等,透過程式語言的使用來減少重複瑣碎的工作,所以若能妥善使用將提升不少開發者和軟體工程師的日常工作效率。
流程步驟
1. 編輯檔案
一般我們會使用 .sh 副檔名來命名 Shell Script 檔案。然後將該檔案設定為可執行:
- 這邊以demo.sh 為範例。
- 更改檔案 +x 的執行權限。
- chmod +x demo.sh
- 可以透過檢視檔案詳細資料觀看是否已有 +x 的執行權限
- $ls -l demo.sh
- # -rwxr-xr-x 1 user staff 106 Nov 16 10:41 demo.sh
2. 第一行: 宣告
- # 宣告使用 /bin/bash
這是Linux預設的Shell 為bash,若你使用的是其他的Shell,如: csh, sh, ksh,請改為 /bin/bash=> /bin/csh....。
3. 程式內容直接使用Shell Command
接著,我們先利用一個簡單的範例:將目前執行 process 的 PID 依照數字大小排序,取出前 10 名,來了解撰寫 Shell Script 的基本架構。
# 宣告使用 /bin/bash
#!/bin/bashecho "=== 將目前執行 process 的 PID 依照數字大小排序,取出前 10 名 === "# ps 為列出 process 相關資訊,透過 | pipe 管線傳遞資料。awk 可以根據 pattern 進行資料處理(這邊印出第一欄 PID)而 sort 是進行排序,其排序時,預設都是把資料當作字串來排序,若想讓資料根據實際數值的大小來排序,可以加上 -n 參數。-r 則是由大到小排序,預設是由小到大ps | awk '{print $1}' | sort -rn | head -10
4. 執行程式=> $ ./demo.sh 或 $ . /demo.sh =>如下結果
Shell Script 語法
定義變數
一般來說程式語言中變數是用來暫存接下來會使用到的資料或是儲存指到物件的參考位置。在 Shell Script 可以使用以下三種方式來宣告變數並給定值:
#!/bin/bashvariable1=value# 若是值內有空白則需要使用 '' 或 "" 包裹起來variable2='value 2'variable3="value 3"
使用變數方式為 ${變數名稱}
#!/bin/bashpathName=demo.sh# echo 是列印值,印出變數 pathName 內容 demo.shecho ${pathName}
刪除變數使用 unset:
#!/bin/bashpathName=demo1.sh# 印出 demo1.shecho ${pathName}pathName=demo2.sh# 印出 demo2.shecho ${pathName}unset pathName# 空值echo ${pathName}
運算式
運算式是當運算子和運算元計算結果回傳後賦值給變數。在 Bash Shell 中內建原生不支援運算式,但我們可以使用 expr、awk 等指令來支援實現運算式。
算式
我們可以使用四則運算來賦值:
#!/bin/bashresult=`expr 10 + 2`# 12echo "Result: $result"
條件判斷
在 Shell Script 中同樣可以使用 if..else 條件判斷,特別注意的是在 Shell Script 中使用 fi 為結尾(為 if 的倒寫法,同樣的接下來討論的 case 也有類似用法),代表條件判斷結束。== 為等於,!= 為不等於運算子。
- if
#!/bin/shx=20y=30if [ $x == $y ]; thenecho "value x is equal to value y"fiif [ $x != $y ]; thenecho "value x is not equal to value y"fi
- if else
在 Shell Script 可以使用 -gt (greater than 縮寫)和 -lt (less than 縮寫)代表大於和小於,而 -ge (greater equal 縮寫)和 -le(less equal 縮寫)則是大於等於和小於等於的運算子符號。
記得比較條件需要放在 [ ] 中,前後要留空白
#!/bin/bashif [ $x -gt $y ]; thenecho "value x is greater than value y"elseecho "value x is not greater than value y"fiif [ $x -lt $y ]; thenecho "value x is not less than value y"elseecho "value x is not less than value y"fiif [ $x -ge $y ]; thenecho "value x is greater or equal than value y"elseecho "value x is not greater than value y"fiif [ $x -le $y ]; thenecho "value x is not less or equal than value y"elseecho "value x is not less or equal than value y"fi
- if elif else
若有多個條件需要判斷,可以使用 if elif else:
#!/bin/bash
value1=20
value2=30
value3=30
if [ $value1 -gt $value2 ]; then
echo "value1 is greater than value2"
elif [ $value1 == $value3 ]; then
echo "value1 is equal to value3"
else
echo "other result"
fi
- case ... esac
若要使用類似一般程式語言的 switch 來處理多種條件判斷時,可以使用 case 來進行判斷:
#!/bin/bashlanguage='Java'case $language inJava*) echo "是 Java!";;Python*) echo "是 Python!";;C*) echo "是 C!";;*) echo "沒 match 到!"esac
迴圈
當我們需要重複某些瑣碎的任務或是迭代取得資料就需要迴圈來支援。此時可以使用 for、while 和 until 迴圈進行迭代。
- for
Shell Script 的 for 使用方法和一般程式語言類似,同樣可以針對條件使用 break、continue 來跳出或是跳過迴圈。
#!/bin/bashfor loop in 1 2 3; doecho "number: $loop"done
- while
若是需要設定一個條件直到該條件為止,可以使用 while,但要注意避免無限迴圈狀況:
#!/bin/bash
counter=0
while [ $counter -le 5 ]; do
counter=`expr $counter + 1`echo $counterdone
- until
直到某個條件結束可以使用 until 來進行:
#!/bin/bash
# 從 0 印出數字直到 10
until [ $counter -gt 10 ]; do
echo $counter
counter=`expr $counter + 1`
done
函式
隨著我們的程式越來越大,我們需要透過模組化或是將重複使用的程式碼改成函式。函式基本架構如下:
- 函式名稱(function 關鍵字為選擇性)
- 是否有傳入參數
- 函式內操作
- 是否有回傳值
functionfunction_name(){
# 做一些事情
[ 回傳值 ]
}
函式範例:
#!/bin/bash
function echoHello() {
# hello world, rock!!echo "${0} hello ${1}, ${2}!!"
}echoHello 'world' 'rock'
以上我們可以看到使用 "" 雙引號把字串和變數取出來印出(你可以試試看使用單引號會發生什麼事情),與一般程式語言比較不同的是其函式呼叫不需要有小括號傳入參數,直接以空白當作參數傳遞的格式。注意參數從 1 開始,${0} 為檔名。
特殊變數
在 Shell Script 檔案和函式往往需要透過傳入參數來設定執行程式的內容。在 Shell Script 支援許多好用的特殊變數,可以方便我們透過使用變數方式來設置程式執行的流程。
- $0 : 目前的檔案檔名
- $nn : 從 1 開始,代表第幾個參數
- $#傳遞到程式或函式目前有幾個參數
- $*傳遞到程式或函式所有參數
- $@類似 $* 但是在被雙引號包含時有些許不同
- $?上一個指令退出狀態或是函式的返回值
- $$目前 process PID
透過執行 ./demo_special_var.sh var1 var2:
#!/bin/bash
echo "$0" echo "$1" echo "$#" echo "$*" echo "$@" echo "$?" echo "$$"
印出結果:
./demo.sh var1 2 var1 var2 var1 var2 0 80417
留言
張貼留言
Aron阿龍,謝謝您的留言互動!