Pass arguments to function exactly as-is

20,288

Solution 1

Use "$@":

$ bar() { echo "$1:$2"; }
$ foo() { bar "$@"; }
$ foo "This is" a test
This is:a

"$@" and "$*" have special meanings:

  • "$@" expands to multiple words without performing expansions for the words (like "$1" "$2" ...).
  • "$*" joins positional parameters with the first character in IFS (or space if IFS is unset or nothing if IFS is empty).

Solution 2

You must use $@, instead of $*

bar() { echo "$1:$2"; }

foo() { bar "$@"; }

foo "This is" a test

ouput

This is:a

Why does it work?

Because with $*, all parameter is seen as a single word, it mean that you will pass This is a test to bar function. In this case, the 1st parameter pass to function bar is This, 2nd is is.

With $@, each parameter is a quoted string, it mean that you will pass 'This is' 'a' 'test' to bar funtion. So the 1st parameter pass to function bar is This is, 2nd is a.

Share:
20,288
Konrad Rudolph
Author by

Konrad Rudolph

I’m a bioinformatician/scientist & software developer. I hold a PhD from the University of Cambridge and EMBL-EBI. I’ve dabbled in everything from biological research (mostly genomics and epigenetics) and statistical analysis (using R) to software development, both on the frontend (using e.g. HTML, JavaScript, WinForms, Swing) and the backend (using C++, Java, Python, Ruby, PHP, to name a few). [he/him] 💜 Sponsor me on GitHub if you would like to support what I’m doing here.

Updated on September 18, 2022

Comments

  • Konrad Rudolph
    Konrad Rudolph almost 2 years

    I have the following function:

    bar() { echo $1:$2; }
    

    I am calling this function from another function, foo. foo itself is called as follows:

    foo "This is" a test
    

    I want to get the following output:

    This is:a
    

    That is, the arguments that bar receives should be the same tokens that I pass into foo.

    How does foo need to be implemented in order to achieve this? I’ve tried the following two implementations, but neither works:

    • foo() { bar $*; }

      – output: this:is

    • foo() { bar "$*"; }

      – output: this is a test:

    My question is effectively how I can preserve the quoting of arguments. Is this possible at all?

  • Konrad Rudolph
    Konrad Rudolph about 11 years
    Thanks, I wasn’t aware that $* had this semantic – now it’s logical. I think this answer actually solves another problem I’ve been having when iterating over arrays …