4

myFun1 and myFun2 below don't produce the same output. Why?

#!/bin/bash

myFun1() { local item IFS=: for item in "${@}"; do echo "->${item}<-" done }

myFun2() { local items="${@}"; local item IFS=: for item in "${items}"; do echo "->${item}<-" done }

Invoking

myFun1 "a=b" "c='d 1'" "e"

produces

->a=b<-
->c='d 1'<-
->e<-

whereas

myFun2 "a=b" "c='d 1'" "e"

produces

->a=b c='d 1' e<-

1 Answers1

5

This behavior is defined by POSIX, which both Bash and Zsh make an effort to adhere to.

@
Expands to the positional parameters, starting from one. When the expansion occurs within double-quotes, and where field splitting (see Field Splitting) is performed, each positional parameter shall expand as a separate field, ...

However, this behavior only applies to $@ itself. Assigning its value to another variable causes the meaning of the individual fields to be lost, and it's then treated as a single string (just as if you used $*).

I'm not certain about Zsh, but if in Bash you want to save $@ to another variable and be able to take advantage of field separation, you need to use an array.

myFun2() {
  local -a items=("${@}");
  local item
  IFS=:
  for item in "${items[@]}"; do
    echo "->${item}<-"
  done
}

In Bash, array expansion of the form "${array[@]}" has the same behavior as "$@".