在 Linux bash shell 中,可以使用位置參數(positional parameters)來擷取傳入腳本、或者傳入函數的各個參數值。
例如,$1 對應傳入的第一個參數,$2 對應傳入的第二個參數。依次類推。
我們可以使用 shift 内置指令來重命名位置參數。
例如,執行 shift 1 指令後,$1 會對應傳入的第二個參數,$2 會對應傳入的第三個參數。依次類推。
檢視 man bash 對 shift 指令的說明如下:
shift [n]
The positional parameters from n+1 ... are renamed to $1 .... Parameters represented by the numbers $# down to $#-n+1 are unset.
n must be a non-negative number less than or equal to $#. If n is 0, no parameters are changed.
If n is not given, it is assumed to be 1. If n is greater than $#, the positional parameters are not changed.
The return status is greater than zero if n is greater than $# or less than zero; otherwise 0.
即,shift 指令基于所給的 n 參數值來重命名位置參數。
把 $1 重命名為 $n+1、$2 重命名為 $n+2,依此類推。
類似于向左移動 n 個位置參數。
如果沒有提供 n 參數,預設值為 1。
所給的 n 必須是大于或等于 0 的整數。
由于 shift 指令的參數不能是負數,當執行該指令重命名位置參數後,無法使用這個指令恢複成原來的位置參數。
執行 shift 指令後,$# 的值會被更新為剩餘的參數個數,[email protected] 隻會擷取到剩餘的參數清單。
當需要把傳入腳本的某個參數之後的所有參數都傳遞給腳本函數時,就可以使用 shift 指令來重命名位置參數,友善引用。
下面以一個 testshift.sh 腳本來舉例說明該指令的用法,腳本内容如下:
(不好意思,近期網頁版文章的代碼塊排版錯亂,背景咨詢确認網頁版不支援。下面用四個 ‘----’ 代替四個空格來進行縮進和隔行顯示。後面的代碼塊會類似處理。如果需要複制代碼到本地驗證,麻煩以四個 ‘----’為機關,替換成四個空格。非常抱歉。)
#!/bin/bash
----
reverse=0
function print_params()
{
----local string="[email protected]"
----if [ $reverse -eq 1 ]; then
--------echo $string | rev
----else
--------echo $string
----fi
}
----
while getopts "r" opt; do
----case $opt in
--------r) reverse=1 ;;
----esac
done
----
shift $((OPTIND-1))
print_params "[email protected]"
這個腳本可以接收一個 -r 選項,提供該選項,則使用 rev 指令反序輸出所給的字元串參數。
如果沒有提供該選項,則正序輸出所給的字元串參數。
當 getopts 指令處理選項參數後,OPTIND 全局變量會被加上選項參數的個數,其值從 1 開始,則 $((OPTIND-1)) 擷取到選項參數個數。
例如執行 ./testshift.sh -r 指令,提供了一個 -r 選項參數,則 getopts 處理這個選項參數後,OPTIND 的值是 2,減去 1 就是選項參數的個數。
使用 shift $((OPTIND-1)) 指令跳過所給的選項參數,之後使用 [email protected] 擷取到的參數清單不包含選項參數。
這些選項參數不需要傳遞給 print_params 函數。
如果這裡不使用 shift 指令,直接寫為 print_params "[email protected]" 語句,那麼 print_params 函數會收到傳入的 -r 選項,且 $1 就是 -r 選項。
那麼函數就需要對這個選項做特殊處理,代碼不夠簡練。
即,如果想要跳過指令行參數的前面幾個參數,把之後的所有參數都統一傳遞給其他地方使用,使用 shift 指令非常友善。
否則需要周遊指令行參數來擷取後面的所有參數值,單獨儲存起來,然後再傳遞,這樣比較麻煩。
執行 testshift.sh 腳本,結果如下:
$ ./testshift.sh 客上天然居 人過大佛寺
客上天然居 人過大佛寺
$ ./testshift.sh -r 客上天然居 人過大佛寺
寺佛大過人 居然天上客
可以看到,“./testshift.sh -r 客上天然居 人過大佛寺” 指令提供了 -r 選項,會反序列印所給的字元串參數。
由于使用了 shift 指令,這個 -r 選項沒有傳遞給 print_params 函數,列印的内容不包含這個選項。