访问函数内Bash脚本的参数

时间:2010-10-19 07:10:41

标签: bash

在函数内部,$1 ... $n是传递给该函数的参数。 函数$1 ... $n之外是传递给脚本的参数。

我可以以某种方式访问​​传递给函数内部脚本的参数吗?

6 个答案:

答案 0 :(得分:21)

通常你只是在调用时将它们作为参数传递给函数。

(丑陋的)替代方案是将它们放在全局变量中。

答案 1 :(得分:18)

(我知道这是一个老帖子,但没有一个答案实际上回答了这个问题。)

使用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
}

答案 2 :(得分:11)

正如Benoit所说,最简单的解决方案是将命令行参数作为函数参数传递给函数$@,然后您可以以与函数外部完全相同的方式引用它们。您实际上将引用传递给函数的值,这些值碰巧与命令行参数具有相同的值,请记住这一点。

请注意,除非您确切知道将在命令行传递多少个参数,否则这几乎会阻止您将任何其他参数传递给该函数(不太可能因为这取决于用户并且不受约束条件的约束)

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

    # $@ represents all the arguments passed at the command line #
    fname $@

更好的方法是仅传递您将要使用的参数,这样您就可以在函数中使用它们并且如果您愿意,还可以从代码中传递其他参数

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

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

答案 3 :(得分:6)

您可以将所有脚本参数存储在全局数组中:

args=("$@")

然后在函数中访问它们:

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

答案 4 :(得分:4)

你应该使用"$@"并在函数参数列表的末尾传递它。解析参数后,在函数内shift,并正常使用$1$n

答案 5 :(得分:0)

感谢您的提示 - 他们激励我编写一个callstack函数。我使用了&#39;列&#39;美学的命令。

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 "$@"; exit ;; # process jpg or pdf
sm --quiet --process brother_001270.pdf   |0