Bash Cheatsheet - 腳本的小抄大全
前言
最近寫了很多腳本,但是有太多參數會忘記了,這篇文章主要是整理了一些常用的 bash 腳本技巧,包括變數、邏輯判斷、迴圈、重導向、子殼層、Here Documents 等等。
1. Built-in Variables
1 | $0, $1, $2 # 第 n 個參數,即 argv[n] |
2. Bash Builins
數學運算,這兩個寫法等價。
1 | echo $((1+1)) |
變數,{} 可省略
1 | name="Shannon" |
指令替換,兩個寫法等價
1 | echo $(whoami) |
展開
1 | echo {1..5} // 1 2 3 4 5 |
3. Logic Statement
binary comparison operator 常見可以參考 Advanced Bash-Scripting Guide
1 | # 前面成功執行的話,後面才會執行 |
字串用 ><= 一類的符號,數字則是用英文縮寫.詳細可以參考 3.1, 3.2 章節
1 | if [ $age -ge 65 ] && [ $name == "John" ]; then |
3.1 Boolean Operation
1 | ! #not |
1 | # 變數 num 比 10 小 『或是』 比 100 大 |
3.2 Integer Opteraion
1 | # -eq: is equal to |
3.3 String Comparision
在 Bash 中,=
和 ==
都用來進行字串比較,但它們之間有一些微妙的差異,特別是在單中括號([ ]
)和雙中括號([[ ]]
)中的行為有所不同。
=
比較符號
單中括號 [ "$a" = "$b" ]
- 語法:
[ "$a" = "$b" ]
- 功能:這是最基本的字串比較,用於檢查兩個字串是否相等。
- 注意事項:一定要注意空格。在
[ "$a" = "$b" ]
中,=
兩側必須有空格。如果缺少空格,如[ "$a"="$b" ]
,這樣的比較會導致錯誤,因為=
會被誤認為是命令的一部分。
範例:
1 | a="apple" |
==
比較符號
單中括號 [ "$a" == "$b" ]
和雙中括號 [[ "$a" == "$b" ]]
- 語法:
[ "$a" == "$b" ]
或[[ "$a" == "$b" ]]
- 功能:
==
在某些情況下可以用來比較字串,但在單中括號([ ]
)中,==
和=
基本上是等效的。唯一的區別在於,==
可以在雙中括號([[ ]]
)中使用更多的功能,並且會支援模式匹配(pattern matching)。 - 注意事項:
- 在單中括號中,
==
和=
是相同的,兩者都用來比較字串。 - 在雙中括號中,
==
支援字串的模式匹配(例如通配符匹配),這是=
所不支援的。 - 單中括號中的
==
行為類似於=
,但在雙中括號中,==
可以進行模式匹配。
- 在單中括號中,
範例(單中括號):
1 | a="apple" |
範例(雙中括號,模式匹配):
1 | a="apple" |
==
與 =
的差異
- 單中括號
[ ]
:- 在
[ "$a" == "$b" ]
和[ "$a" = "$b" ]
中,==
和=
基本上是等效的。 - 它們都比較字串是否相等。
- 在
- 雙中括號
[[ ]]
:- 在
[[ "$a" == "$b" ]]
中,==
會進行模式匹配,因此支持通配符(如*
或?
)。 - 而
=
只是做簡單的字串比較,不支持模式匹配。
- 在
4. Loop
for each,這兩種 array 存取值的寫法是等價的
1 | arr=(Alice Bob Oscar) |
也可以使用 C-style for loop
1 | for (( i=1; i<=5; i++ )); do |
while Loop
1 | i=0 |
5. Redirection
1 | echo john | grep 'john' # pipe,第一個指令的 stdout 作為第二個指令的 stdin |
6. Subshell (bash parallel script)
這段內容主要解釋了 子殼層 (subshell) 和 父殼層 (parent shell) 之間的執行行為,並說明了如何使用 &
來達到並行執行的效果。
基本的子殼層 (()
的用法)
1 | (sleep 5) |
(sleep 5)
這段程式碼會在一個 子殼層 中執行。子殼層是一個新的 shell 進程,它會從父殼層繼承環境變數等設定,但執行的指令會在這個子殼層中處理。sleep 5
會讓這個子殼層暫停 5 秒。- 然後,
echo done
在父殼層中執行。
注意:
- 如果你只是寫
(sleep 5)
,父殼層會等待這個子殼層完成後再繼續執行下面的指令(即echo done
)。這是因為沒有使用&
,父殼層會「等待」子殼層執行完成。 - 所以,這段程式碼的結果是:子殼層執行
sleep 5
,父殼層會等待 5 秒,然後才顯示done
。
使用 &
讓父殼層不等待子殼層
1 | (sleep 2; echo child) & |
(sleep 2; echo child)
這段程式碼放在子殼層中執行,並且加上了&
,表示 將子殼層的執行放到背景進行。&
讓父殼層不會等子殼層執行完成,而是會繼續執行後續的指令。echo parent
在父殼層中立即執行。
結果:
- 子殼層會執行
sleep 2
然後顯示child
,這需要 2 秒鐘。 - 父殼層會立即執行
echo parent
,所以會先顯示parent
。 - 兩個
echo
命令是並行執行的,這就達到了平行處理的效果。
7. Here Documents
什麼是 “Here Document”?
這個名稱的概念來自:「這裡 (here) 就有一份文件 (document)」 → 你不需要從外部讀取,而是直接在腳本內提供多行內容。對應傳統 Shell Script 的標準輸入 (stdin) → 通常程式需要用 < file.txt 讀取外部檔案,但 Here Document 讓你直接內嵌資料。
📌 具體比較
方法 | 輸入來源 | 描述 |
---|---|---|
< file.txt |
外部檔案 | 讀取 file.txt 內容當作標準輸入 |
<<EOF ... EOF |
內嵌內容 | 直接在腳本內提供多行內容 |
傳統方式(讀取外部檔案)
1 | cat < myfile.txt |
Here Document(直接提供內容)
1 | cat <<EOF |
總結來說:
Here Document 讓 Shell Script 不需要額外的檔案,而可以直接在 “這裡 (here)” 定義輸入,這就是它名稱的由來!
什麼是EOF?
EOF 的全名是 “End of File”,意思是「檔案結束」。在 Here Document 的語境中,EOF 只是個常見的 標記 (delimiter),它本身沒有特別的語法意義。你可以用任何字串作為結束標記,但 EOF 是最常見的約定俗成的標記,因為它表示「這段輸入的結束」。
例如:
1 | cat <<MYMARKER |
Refernece
- Minimal safe Bash script template
- Advanced Bash-Scripting Guide: 如果真的要精通 bash ,可以讀一下,小心不要走火入魔
- Google | Style Guide - Shell Guide 本篇文章的主要來源