Shell – How to use variables with values containing spaces in a Z-shell (zsh) script command

shell-scriptzsh

I have the following Z-shell script:

compiler=clang++
standard=-std=c++11
warnings="-Wall -Wextra -Wpedantic"
${compiler} ${warnings} ${standard} -o ${1} ${1}.cpp

This does not work as the ${warnings} variable appears to be seen as
"-Wall -Wextra -Wpedantic" – that is one long warning with spaces, versus three separate warnings.

I did some searching and was able to get it to work with eval:

eval "${compiler} ${warnings} ${standard} -o ${1} ${1}.cpp"

However, I am confused as to why it is necessary, and also is there some other way to correct this issue.

EDIT: In addition to doing it as shown in Peter O. 's answer, I found that you can do:

setopt shwordsplit

to get the Z-shell to behave like other Bourne shell derivatives. As they say in their FAQ:

In most Bourne-shell derivatives, multiple-word variables such as

var="foo bar"

are split into words when passed to a command or used in a for foo in
$var loop. By default, zsh does not have that behaviour: the variable
remains intact. (This is not a bug! See below.) The option
SH_WORD_SPLIT exists to provide compatibility.

Best Answer

Set your Warning options as an array. "${warnings[@]}" generates 3 individual words

warnings=(-Wall -Wextra -Wpedantic)

"${compiler}" "${warnings[@]}" "${standard}" -o "${1}" "${1}.cpp"

Or, if you find it more legible, you can create the array without -W's, and then add -W's via how you present the array on the command line.

warnings=( all extra pedantic )

"${compiler}" "${warnings[@]/#/-W}" "${standard}" -o "${1}" "${1}.cpp"
Related Question