特殊變量
首先來看幾個特殊變量:
1 #!/bin/bash 2 echo $0 # 當前腳本的文件名(間接運行時還包括絕對路徑)。 3 echo $n # 傳遞給腳本或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是 $1 。 4 echo $# # 傳遞給腳本或函數的參數個數。 5 echo $* # 傳遞給腳本或函數的所有參數。 6 echo $@ # 傳遞給腳本或函數的所有參數。被雙引號 (" ") 包含時,與 $* 不同,下面將會講到。 7 echo $? # 上個命令的退出狀態,或函數的返回值。 8 echo $$ # 當前 Shell 進程 ID。對於 Shell 腳本,就是這些腳本所在的進程 ID。 9 echo $_ # 上一個命令的最后一個參數。 10 echo $! # 后台運行的最后一個進程的 ID 號。
保存為一個腳本,然后加上幾個參數運行,結果如下:
1 $ ./test.sh A B B D E 2 ./test.sh # $0, 當前腳本的文件名(間接運行時還包括絕對路徑)。 3 # $n, 傳遞給腳本或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是 $1。 4 5 # $#, 傳遞給腳本或函數的參數個數。 5 A B B D E # $*, 傳遞給腳本或函數的所有參數。 6 A B B D E # $@, 傳遞給腳本或函數的所有參數。被雙引號 (" ") 包含時,與 $* 不同,下面將會講到。 7 0 # $?, 上個命令的退出狀態,或函數的返回值。 8 24946 # $$, 當前 Shell 進程 ID。對於 Shell 腳本,就是這些腳本所在的進程 ID。 9 24946 # $_, 上一個命令的最后一個參數。 10 # $!, 后台運行的最后一個進程的 ID 號。
$*
和 $@
都表示傳遞給函數或腳本的所有參數,不被雙引號 ("") 包含時,都以 "$1""$2" … "$n" 的形式輸出所有參數。但是當它們被雙引號 ("") 包含時,"$*
"會將所有的參數作為一個整體,以 "$1 $2 … $n" 的形式輸出所有參數; "$@
"會將各個參數分開,以 "$1"、"$2"、…、"$n" 的形式輸出所有參數。
#!/bin/bash echo "\$* = " $* echo "\"\$*\" = " "$*" echo "\$@ = " $@ echo "\"\$@\" = " "$@" echo "打印 \$* 中的每一個參數: " for var in $* do echo "$var" done echo "打印 \$@ 中的每一個參數: " for var in $@ do echo "$var" done echo "從 \"\$*\" 獲取並打印每一個參數: " for var in "$*" do echo "$var" done echo "從 \"\$@\" 獲取並打印每一個參數: " for var in "$@" do echo "$var" done
運行及輸出:
1 $ ./test.sh A B B D E 2 $* = A B B D E 3 "$*" = A B B D E 4 $@ = A B B D E 5 "$@" = A B B D E 6 打印 $* 中的每一個參數: 7 A 8 B 9 B 10 D 11 E 12 打印 $@ 中的每一個參數: 13 A 14 B 15 B 16 D 17 E 18 從 "$*" 獲取並打印每一個參數: 19 A B B D E 20 從 "$@" 獲取並打印每一個參數: 21 A 22 B 23 B 24 D 25 E
shift 使用
shift
命令用於對參數的移動(左移),通常用於在不知道傳入參數個數的情況下依次遍歷每個參數然后進行相應處理,常見於 Linux 中各種程序的啟動腳本。
1. 每次移動一個參數
示例:依次讀取輸入的參數並打印參數個數
- shift1.sh
1 #!/bin/bash 2 while [ $# != 0 ] 3 do 4 echo -e "參數值為 $1, 參數個數為 $#" 5 shift 6 done
輸入如下命令運行:
1 $ sh shift1.sh a b c d 2 參數值為 a, 參數個數為 4 3 參數值為 b, 參數個數為 3 4 參數值為 c, 參數個數為 2 5 參數值為 d, 參數個數為 1
每次運行 shift(不帶參數的),銷毀一個參數(變量的個數($#)減一),后面的參數前移(不管參數之間相隔一個或者多個空格)。
2. 每次移動多個參數
shift 命令一次移動參數的個數由其所帶的參數指定。例如,現在有 $1, $2, $3, ...,$9 個參數,當 shell 程序處理完前 4 個命令行參數后(即還剩下后面 5 個參數),可以使用 shift 4
命令把 $9 移到 $1。
示例:自定義 shift 每次移動的參數個數。
- shift2.sh
1 #!/bin/bash 2 while [ $# -gt 5 ] 3 do 4 echo -e "參數值為 $1, 參數個數為 $#" 5 shift 6 done 7 shift 4 8 echo -e "參數值為 $1, 參數個數為 $#"
輸入如下命令運行
1 $ sh shift2.sh a1 b2 c3 d4 e5 f6 g7 h8 i9 2 參數值為 a1, 參數個數為 9 3 參數值為 b2, 參數個數為 8 4 參數值為 c3, 參數個數為 7 5 參數值為 d4, 參數個數為 6 6 參數值為 i9, 參數個數為 1
3. 常與 case 條件配合使用
case ..... esac
和 if ... then ... fi
一樣,都是條件判斷式的語句結構,它們用倒序的字母單詞和正序的單詞配對,比如 if
語句,結束時用 fi
來配對, esac
和 case
配對,是多路分支的語句,類似於 C 中的 switch/case
語句,大致形式如下:
1 case $參數變量 in # 以關鍵字 case 作為開始 2 "變量值1") # 變量值用雙引號括起來,關鍵字用小括號括起來 3 程序段1 # 對應的邏輯 4 ;; # 每個類別結尾使用兩個連續的分號來處理 5 "變量值2") 6 程序段2 7 ;; 8 "變量值3") 9 程序段3 10 ;; 11 *) # 最后一個位置參數值會用*來代替所有其他值 12 程序段4 13 ;; 14 esac # 關鍵字 esac(case 的反寫) 結束
shift
操作經常與 case ... esac
條件分支配合使用。
示例: shift
搭配 case ... esac
實現 shell 腳本手動傳遞參數處理
- shift3.sh
1 while [ -n "$1" ] 2 do 3 case "$1" in 4 -a) 5 echo "發現 -a 選項" 6 ;; 7 -b) 8 echo "發現 -b 選項" 9 echo "-b 選項的參數值是:$2" 10 shift 11 ;; 12 -c) 13 echo "發現 -c 選項" 14 echo "-c 選項的參數值是:$2" 15 shift 16 ;; 17 *) 18 echo "$1 是一個未知選項" 19 ;; 20 esac 21 shift 22 done
輸入如下命令運行
1 $ sh shift3.sh -a -b 200 -c 300 -d 400 2 發現 -a 選項 3 發現 -b 選項 4 -b 選項的參數值是:200 5 發現 -c 選項 6 -c 選項的參數值是:300 7 -d 是一個未知選項 8 400 是一個未知選項
轉載於:https://www.yuque.com/shenweiyan/cookbook/shell-shift-note