12

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
  • 3,689
  • 3
  • 23
  • 29
  • Related: [How do I use a Bash variable (string) containing quotes in a command?](https://superuser.com/q/360966/11574) –  May 30 '18 at 16:16

2 Answers2

17

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).
Lri
  • 5,143
  • 2
  • 27
  • 20
  • 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 06 '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.

cuonglm
  • 150,973
  • 38
  • 327
  • 406