Bash Script Cheatsheet

3 minute read

被 bash 一堆特殊符號,還有語法格式衝昏頭了嗎?這篇文章會在幾分鐘內,快速介紹 bash script 的常用的一些特殊語法。

這不是 bash script 教學,也不是一分冗長的文件說明,這是 cheatsheet ,言簡意賅才是重點!

Built-in Variables

$0, $1, $2 # 第 n 個參數,即 argv[n]
$# # 參數數量,即 argc
$@ # 所有的參數
$? # 上一個指令的回傳值
$$ # 目前程式的 pid
$! # 上一個在背景執行的程式的 pid

Bash Builtins

  • 數學運算,前兩個寫法等價
echo $((1+1))
echo $[1+1]
  • 變數,{} 可省略
name="John"
echo $name
echo ${name}

# 字串長度
echo ${#name} # 4
  • 指令替換,兩個寫法等價
echo $(whoami)
echo `whoami`
  • 展開
echo {1..5} // 1 2 3 4 5
echo {1..10..2} // 1 3 5 7 9

Logic Statement

  • bash shortcut
echo hi && echo john # 前面成功執行的話,後面才會執行
grep 'notfound' /dev/null || echo 'Not found' # 前面指令失敗的話,後面才會執行
  • if-else

字串用 ><= 一類的符號,數字則是用英文縮寫

if [ $age -ge 65 ] && [ $name == "John" ]; then
  echo '...'
fi
  • 那些數字大小於的英文縮寫,如果記不起來的話考以參考這裡

  • 檢查檔案存在相關屬性的,請參考這裡

Loop

  • for each,這兩種 array 存取值的寫法是等價的
arr=(Alice Bob Oscar)
for i in {0..2}; do
  echo ${arr[i]}
done

for i in "${arr[@]}"; do
  echo $i
done
  • C-style for loop
for (( i=1; i<=5; i++ )); do
  echo $i
done
  • while Loop
i=0
while [ $i -lt 5 ]; do
  echo $i
  ((i++)) # 雙括號裡面可以寫 C-style 的運算式
done

Redirection

echo john | grep 'john' # pipe,第一個指令的 stdout 作為第二個指令的 stdin
echo hi > /tmp/text # stdout 輸出導向檔案並覆寫
echo hi >> /tmp/text # stdout 輸出導向檔案,附加在該檔案內容後
echo hi 2>&1 # stderr 導向 stdout
echo hi 1>&2 # stdout 導向 stderr
echo hi &> /tmp/text # stdout 與 stderr 都導向檔案
cat < /tmp/text # stdin 改從檔案讀入
cat <(echo hi) # 把括號中的輸出丟到 cat 指令當 stdin 

Subshell (bash parallel script)

只寫 () 的話 parent 會 wait subshell,這樣會失去平行的意義

(sleep 5)
echo done

加上 & 就可以讓 parent 不等 subshell,兩個 process 同時執行

(sleep 2; echo child) &
echo parent

Bash good practice

set -e # 只要遇到失敗的指令,就會立刻退出
set -x # 印出每個執行的指令

Reference: Johns Blog · Bash Cheat Sheet

其他什麼 function 之類的就不寫了。

我個人通常不會把 bash script 寫的太長,如果需要寫比較長的 script,我傾向用 Python3 + bash 來完成,不但結合 Python3 處理字串、數學運算、高可讀性的優點,也充分發揮 bash 指令的便捷性。

如果真的要精通 bash ,可以讀一下 Advanced Bash-Scripting Guide,小心不要走火入魔……


後記

本來以為我可以算是「會寫」 bash script、script language 的人,但我 2017 年上旬去 Yahoo summer intern interview 的時候,面試官就問了我一些題目,例如$@$*的差別, 還有 set -exfind, xargs 的一些用法,我幾乎都答不出來。

很明顯我看別人的 script ,加上自己寫的 script 都不夠多,現階段充其量也只能算是「略懂略懂」吧。

你熟悉 Linux 作業系統嗎?我看就連 Linux Torvald 對當今的 kernel - Linux 4.10,恐怕也會謙虛的說道他「略懂」 Linux 系統吧!