开发者

Access arguments to Bash script inside a function [duplicate]

This question already has answers here: How to access command line arguments of the caller inside a function? (10 answers) Closed 5 years ago.

Inside a function, $1 ... $n are the parameters passed to that function. Outside a function $1 ... $n are the paramete开发者_如何学运维rs passed to the script.

Can I somehow access the parameters passed to the script inside a function?


Usually you just pass them as parameters to the function at call time.

The (uglier) alternative is to put them in global variables.


(I know this is an old post, but none of the answers actually answered the question.)

Use the BASH_ARGV array. It contains the arguments passed to the invoking script in reverse order (i.e., it's a stack with the top at index 0). You may have to turn on extended debugging in the shebang (e.g., #!/bin/bash -O extdebug) or with shopt (e.g., shopt -s extdebug), but it works for me in bash 4.2_p37 without it turned on.

From man bash:

An array variable containing all of the parameters in the current bash execution call stack. The final parameter of the last subroutine call is at the top of the stack; the first parameter of the initial call is at the bottom. When a subroutine is executed, the parameters supplied are pushed onto BASH_ARGV. The shell sets BASH_ARGV only when in extended debugging mode….

Here's a function I use to print all arguments in order on a single line:

# 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
}


As Benoit stated, the simplest solution is to pass the commandline arguments to the function as function arguments with $@, then you can reference them in exactly the same way as outside the function. You'll actually be referencing the values passed to the function that just happen to have the same value as the commandline arguments, keep that in mind.

Note that this pretty much precludes you from passing any other arguments to the function, unless you know exactly how many arguments will be passed at the command line (unlikely as that is up to the user and isn't bound by your constraints)

i.e.

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

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

A better way is to pass only the arguments you know you will be using, that way you can use them in the function AND also pass other parameters from within your code if you wish

i.e.

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

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


You can store all of your script arguments in a global array:

args=("$@")

and then access them in a function:

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


You should probably use "$@" and pass that at the end of your function's argument list. Inside the function, shift after parsing your arguments and use $1 to $n as normally.


Thanks for the tips - they inspired me to write a callstack function. I used the 'column' command for esthetics.

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜