Bash技巧:使用 shift 內置命令左移前幾個命令參數

Bash技巧:使用 shift 內置命令左移前幾個命令參數

在 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 命令後,$# 的值會被更新為剩餘的參數個數,$@ 只會獲取到剩餘的參數列表。

當需要把傳入腳本的某個參數之後的所有參數都傳遞給腳本函數時,就可以使用 shift 命令來重命名位置參數,方便引用。

下面以一個 testshift.sh 腳本來舉例說明該命令的用法,腳本內容如下:

(不好意思,近期網頁版文章的代碼塊排版錯亂,後臺諮詢確認網頁版不支持。下面用四個 ‘----’ 代替四個空格來進行縮進和隔行顯示。後面的代碼塊會類似處理。如果需要複製代碼到本地驗證,麻煩以四個 ‘----’為單位,替換成四個空格。非常抱歉。)

#!/bin/bash

----

reverse=0

function print_params()

{

----local string="$@"

----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 "$@"

這個腳本可以接收一個 -r 選項,提供該選項,則使用 rev 命令反序輸出所給的字符串參數。
如果沒有提供該選項,則正序輸出所給的字符串參數。

當 getopts 命令處理選項參數後,OPTIND 全局變量會被加上選項參數的個數,其值從 1 開始,則 $((OPTIND-1)) 獲取到選項參數個數。
例如執行 ./testshift.sh -r 命令,提供了一個 -r 選項參數,則 getopts 處理這個選項參數後,OPTIND 的值是 2,減去 1 就是選項參數的個數。

使用 shift $((OPTIND-1)) 命令跳過所給的選項參數,之後使用 $@ 獲取到的參數列表不包含選項參數。
這些選項參數不需要傳遞給 print_params 函數。

如果這裡不使用 shift 命令,直接寫為 print_params "$@" 語句,那麼 print_params 函數會收到傳入的 -r 選項,且 $1 就是 -r 選項。
那麼函數就需要對這個選項做特殊處理,代碼不夠簡練。

即,如果想要跳過命令行參數的前面幾個參數,把之後的所有參數都統一傳遞給其他地方使用,使用 shift 命令非常方便。
否則需要遍歷命令行參數來獲取後面的所有參數值,單獨保存起來,然後再傳遞,這樣比較麻煩。

執行 testshift.sh 腳本,結果如下:

$ ./testshift.sh 客上天然居 人過大佛寺

客上天然居 人過大佛寺

$ ./testshift.sh -r 客上天然居 人過大佛寺

寺佛大過人 居然天上客

可以看到,“./testshift.sh -r 客上天然居 人過大佛寺” 命令提供了 -r 選項,會反序打印所給的字符串參數。
由於使用了 shift 命令,這個 -r 選項沒有傳遞給 print_params 函數,打印的內容不包含這個選項。


分享到:


相關文章: