2014-09-26 70 views
1

我正在整理一些bash的代碼。我有一堆行,像下面的例子那樣設置變量,除非已經設置了,使用給腳本的命令行參數。bash函數可以訪問和操作腳本的命令行參數嗎?

[[ -z "${myvar1}" && -n $1 ]] && myvar1="$1" && shift 
[[ -z "${myvar2}" && -n $1 ]] && myvar2="$1" && shift 
...repeated many times... 

我想我會寫一個函數來做到這一點,這樣稱呼它

positional_arg myvar1 
positional_arg myvar2 

然而,這需要的功能來訪問和操作的參數列表。我不知道這是可能的,所以這是我想出了...

args=("[email protected]") 
positional_arg() { 
    local value=$args 
    [[ -z "${!1}" && -n "$value" ]] && eval "$1='$value'" && args=(${args[@]:1}) 
} 

,我知道這樣做的問題是,

  • 這取決於全球args陣列使用前設置
  • 構造args=(${args[@]:1})其中轉變該數組不適用於空白,所以這將不適用於包含空白的參數。

所以,我想發現一個函數是否可以訪問和操作其腳本的位置參數。

另外,在bash中實現這種功能的任何替代建議都會受到歡迎,特別是如果它們克服了上述問題!

(GNU bash, version 4.3.18(1)-release) 

回答

2

首先,你可能要考慮使用簡單

: ${myvar1:=$1} 
: ${myvar2:=$2} 
# etc 

這只是設置myvar1$1值(空或不)僅如果myvar1已經沒有非空值。


local args=(${args[@]:1})不保留空白,但local args=("${args[@]:1}")一樣。

由於[email protected]同時用於shell和函數的位置參數,所以在調用函數之前,您將不得不將shell參數複製到已知的全局變量中。當然,如果你真的想修改的參數,你還必須在函數返回後(如args=("[email protected]"); my_function; set -- "${args[@]}")複製它們。

另一種方法是通過外殼參數作爲附加功能參數:

my-function() { 
    local_args=() 
    while [[ $1 != "--" ]]; do 
     local_args+=("$1") 
     shift 
    done 
    shift 
    # [email protected] is now a copy of the shell arguments, 
    # but you'll still have to copy them to a global 
    # if you want to make any changes visible post-call 
} 
my-function arg1 args2 -- "[email protected]" 
+0

感謝您的空白修復!你可以在你的例子中解釋'set - 「$ {args [@]}」'「嗎? – starfry 2014-09-26 14:44:57

+0

@starfry,它從'args'數組中設置參數列表('$ 1','$ 2'等)。 – 2014-09-26 14:59:59

+0

@chepner:我最初有'$ {myvar1:= $ 1} ...'但改變了它,因爲位置參數分配是在用'getopts'解析選項來填充仍然未分配的變量之後出現的。因此,變量到參數的映射根據選項的使用情況而變化。但是,是的,在一致的情況下,我正是這樣做的。 – starfry 2014-09-27 10:36:58

2

您也可以在一個循環中間接設置的變量(不potentionally危險EVAL):

#!/bin/bash 

#set variables in order from "[email protected]" 
for var in myvar1 myvar2 v3 x   #names of the variables... 
do 
    #use one of the following to assgin to the variable 
    printf -v "$var" "%s" "$1" && shift #print into variable 
    #read -r "$var" <<< "$1" && shift #read into variable 
    #declare "$var"="$1" && shift  #declare a variable 
done 

#print the content of the variables 
echo "=$myvar1=$myvar2=$v3=$x=" 

#or indirectly: 
for var in myvar1 myvar2 v3 x 
do 
    echo "$var:>>${!var}<<" 
done 
echo "Unused/remaining args:" 
printf ">>%s<<\n" "[email protected]" 

什麼調用如:

script '1 1' 2 3 '4 4' 5 6 

打印

=1 1=2=3=4 4= 
myvar1:>>1 1<< 
myvar2:>>2<< 
v3:>>3<< 
x:>>4 4<< 
Unused/remaining args: 
>>5<< 
>>6<< 

總之,使用非常重要的位置因變量是未來難以調試的源泉......恕我直言,在情況下,當腳本必須採取很多不同的變量,是更好地使用getopt並使用腳本

script -i vali -o valo .... -z valz # ;) 
+0

避免邪惡'eval'總是好事!那裏有用的提示;我必須至少承諾其中之一才能回憶。另外,在處理位置參數之前,我正在使用'getopts'。兩種方式都有其優點。我只是在@ chepner的回答評論中描述了我正在做的事情。謝謝你的建議,謝謝。 – starfry 2014-09-27 10:48:32

0

最簡單的方法是調用positional_arg[email protected]

positional_arg [email protected] 

通過它的命令行變量然後,你將獲得牛逼他在函數內部使用命令行參數,使用$1,$2等。

$0將是腳本的名稱。

如果您需要發送更多變量,您可以簡單地將它們添加到命令行參數之後。

positional_arg [email protected] $test 

這隻會增加數組的大小。

,如果這是你的一個問題,簡單的前[email protected]

positional_arg $test [email protected] 

添加其他變量,在這種情況下,你知道你有多少變量發送的功能,因此,你可以在做津貼的你的函數中的變量調用。

$0在這種情況下,仍然是腳本的名稱,所有其他引用都會增加您添加的變量的數量。

在上面的例子中$1函數調用之前,變成$2函數內。

+0

想法是'positions_arg'函數從全局列表中吃掉了arg。 – starfry 2017-07-16 12:51:33

相關問題