3

I want to limit the change to the separator only to the following echo command not to the shell:

$ myarr=(1 2 3)
$ echo $( IFS="|"; echo "${myarr[@]}" )
1 2 3
$ echo $( ( IFS="|"; echo "${myarr[@]}" ) )
1 2 3

Why doesn't the separator works for array expansion? Thanks.

  • 1
    According to man bash, "${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS special variable, and ${name[@]} expands each element of name to a separate word." – steeldriver Jun 2 '18 at 1:30
  • To encapsulate the answers: using * expands to a single string; using @ expands to individual elements. But for both, only when the expansion is quoted: echo "${a[*]}" not echo ${a[*]} and for elem in "${a[@]}" not for elem in ${a[@]} – glenn jackman Jun 2 '18 at 14:01
4

From POSIX, regarding $*:

When the expansion occurs in a context where field splitting will not be performed, the initial fields shall be joined to form a single field with the value of each parameter separated by the first character of the IFS variable if IFS contains at least one character, or separated by a <space> if IFS is unset, or with no separation if IFS is set to a null string.

To join words with a separator, you will have to use $*, or ${array[*]} in bash:

$ set -- word1 word2 word3 "some other thing" word4
$ IFS='|'
$ echo "$*"
word1|word2|word3|some other thing|word4

Or, with an array in bash:

$ arr=( word1 word2 word3 "some other thing" word4 )
$ IFS='|'
$ echo "${arr[*]}"
word1|word2|word3|some other thing|word4

With your code:

$ myarr=( 1 2 3 )
$ echo $( IFS="|"; echo "${myarr[*]}" )
1|2|3
2

Compare:

$ myarr=(1 2 3)
$ printf '%s\n' $( IFS="|"; echo "${myarr[@]}" )
1 2 3
$ printf '%s\n' $( ( IFS="|"; echo "${myarr[*]}" ) )
1|2|3

From man bash:

@
… When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$@" is equivalent to "$1" "$2" ...

*
… When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable. That is, "$*" is equivalent to "$1c$2c...", where c is the first character of the value of the IFS variable.

The description above is for positional parameters but it also apply to array expansions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.