6

In my-script, "$1" is a string of tokens, separated by whitespace.

how can I "spread" this single argument into multiple arguments to pass to another program for example

./my-script2 ...$1  # spread the string into multiple arguments, delineating by whitepace

Hopefully you understand the question, had trouble searching for answer to this.

I tried this:

./my-script2 <<< "$1"

and this:

./my-script2 "" <<< $1

and other combinations, but that didn't seem to work. I need to support Bash v3 and above.

2 Answers2

8
./my-script2 $1

Unquoted parameters are subject to word splitting when expanded:

The shell scans the results of parameter expansion, command substitution, and arithmetic expansion that did not occur within double quotes for word splitting.

This is the specified POSIX behaviour, though some shells (notably zsh) disable it by default. If you've changed the value of IFS from the default, that's on you.

Michael Homer
  • 76,565
3

Abstract: A "filename expansion" safe solution (for my-script2):

IFS=' ' read -a arr <<<"$1"
printf '<%s>--' "${arr[@]}" ; echo

The naive solution of using the variable un-quoted to get it divided into words (based on IFS value) also expose the contents to filename expansion on *, ? and [ (at least).

This specific string works correctly:

$ set "a string with spaces"
$ printf '<%s>--' $1; echo
<a>--<string>--<with>--<spaces>--

But this string clearly fails:

$ set "a bad * string with spaces"
$ printf '<%s>--' $1; echo
<a>--<bad>--<file1>--<file2>--<string>--<with>--<spaces>--

The asterisk got expanded into the files in PWD.

Here-doc

One way (very often overlooked but also very useful) to get variable expansion without "pathname expansion" is to use a here-document.

IFS=' ' read -ra arr <<-_EOF_
 $1
 _EOF_
 printf '<%s>--' "${arr[@]}" ; echo;

As explained in the manual:

If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, … …

Please note that "pathname expansion" is not applied.

The cousin of a here-document is the here-string, which makes the code shorter:

IFS=' ' read -ra arr <<<"$1"
printf '<%s>--' "${arr[@]}" ; echo;

Just remember that (as inside double quotes) the characters \, $, and ` are special.
From the manual:

the character sequence \ is ignored, and \ must be used to quote the characters \, $, and `