2010-10-19 22 views
26

函數內部,$1 ... $n是傳遞給該函數的參數。 函數外部$1 ... $n是傳遞給腳本的參數。在函數內訪問Bash腳本的參數

可以以某種方式訪問​​傳遞給函數內部腳本的參數嗎?

回答

20

通常你只是在通話時將它們作爲參數傳遞給函數。 (醜)替代方法是把它們放在全局變量中。

3

您應該使用"[email protected]"並將其傳遞到函數參數列表的末尾。在函數內部,解析參數後使用shift,正常情況下使用$1$n

6

您可以將所有的腳本參數存儲在一個全局數組:

args=("[email protected]") 

,然後在函數訪問它們:

f(){ 
    echo ${args[0]} ${args[1]} 
} 
+1

我認爲'函數f(){'是無效的。你應該使用'f(){'或'function f {'來代替。 – Benoit 2010-10-19 07:28:15

+0

我糾正了我的答案,但函數f(){}'確實爲我工作。 – dogbane 2010-10-19 07:41:02

16

(我知道這是舊的文章,但沒有的答案實際上回答了這個問題。)

使用BASH_ARGV數組。它包含以相反順序傳遞給調用腳本的參數(即,它是一個頂部位於索引0的堆棧)。您可能需要在shebang(例如#!/bin/bash -O extdebug)或shopt(例如shopt -s extdebug)中打開擴展調試,但它在bash 4.2_p37中對我沒有打開效果。

man bash來自:

包含在當前的bash執行調用堆棧的所有參數的數組變量。最後一個子程序調用的最後一個參數位於堆棧的頂部;初始調用的第一個參數在底部。當執行一個子程序時,所提供的參數被壓入BASH_ARGV。只有在擴展調試模式下,shell纔會設置BASH_ARGV ...。

這是我用來打印的所有參數,以便在一行中的函數:

# Print the arguments of the calling script, in order. 
function get_script_args 
{ 
    # Get the number of arguments passed to this script. 
    # (The BASH_ARGV array does not include $0.) 
    local n=${#BASH_ARGV[@]} 

    if (($n > 0)) 
    then 
     # Get the last index of the args in BASH_ARGV. 
     local n_index=$(($n - 1)) 

     # Loop through the indexes from largest to smallest. 
     for i in $(seq ${n_index} -1 0) 
     do 
      # Print a space if necessary. 
      if (($i < $n_index)) 
      then 
       echo -n ' ' 
      fi 

      # Print the actual argument. 
      echo -n "${BASH_ARGV[$i]}" 
     done 

     # Print a newline. 
     echo 
    fi 
} 
+0

相關提示儘管擴展調試聽起來有點可怕。 – zedoo 2012-10-15 18:12:28

10

由於伯努瓦說,最簡單的解決方法是在命令行參數傳遞給函數與[email protected]函數參數,那麼你可以用與函數外部完全相同的方式引用它們。實際上,您將引用傳遞給剛好具有與命令行參數相同的值的函數的值,請牢記這一點。

請注意,這幾乎排除了將任何其他參數傳遞給該函數的可能性,除非您確切知道將在命令行中傳遞多少個參數(不太可能由用戶決定並且不受您的約束)

ie

function fname { 
    # do something with $1 $2 $3...$n # 
    } 

    # [email protected] represents all the arguments passed at the command line # 
    fname [email protected] 

一個更好的辦法是通過只有你知道你將要使用的參數,這樣你可以在函數中使用它們,還從自己的代碼中傳遞其他參數,如果你想

function fname { 
    # do something with $1 $count $2 and $3 # 
    } 

    count=1 
    fname $1 $count $2 $3 
+2

您可以簡單地將參數的固定數量傳遞給參數列表開頭的函數,然後在函數中使用'shift'來處理它們以跳過它們。 **函數調用:**'fname farg1 farg2 farg3「$ @」'**在處理三個參數後的函數中:**'shift 3' – pabouk 2013-08-12 12:18:50

+0

這是一個很好的觀點。 – CaffeineConnoisseur 2013-08-12 23:18:49

+1

你也可以通過調用fname來告訴它有多少用戶參數在使用$#,這樣你不僅可以在之前指定額外的參數,還可以在之後像這樣:'fname beforearg $#「$ @」afterarg' – 2014-02-18 04:47:55

0

感謝您的提示 - 他們激勵我編寫一個callstack函數。我使用'列'命令進行審美。

callstack() { 
    local j=0 k prog=$(basename $0) 
    for ((i=1; ((i<${#BASH_ARGC[*]})); i++)) 
    do 
     echo -n "${FUNCNAME[$i]/main/$prog} " # function name 
     args="" 
     for ((k=0; ((k<${BASH_ARGC[$i]})); k++)) 
     do 
      args="${BASH_ARGV[$j]} $args" # arguments 
      let j++ 
     done 
     echo -e "$args\t|${BASH_LINENO[$i]}" $(sed -n ${BASH_LINENO[$i]}p "$0" 2>/dev/null) # line calling the function 
    done | column -t -s $'\t' -o ' ' | sed 1d # delete callstack entry 
} 
 
compareTemplates brother_001270_1.jpg  |163 compareTemplates "$f" # process the rest 
processPdf brother_001270.pdf    |233 filetype "${f%[*}" pdf && processPdf "$f" 
process brother_001270.pdf    |371 --process) shift; process "[email protected]"; exit ;; # process jpg or pdf 
sm --quiet --process brother_001270.pdf |0