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<-
2

1 Answer 1

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 "$@".

1
  • Also please keep in mind that shell arrays are not part of POSIX.
    – schily
    Commented Aug 21, 2021 at 14:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .