9

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?

12

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).
  • 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 … – Konrad Rudolph Jun 6 '13 at 16:29
6

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.