Search code examples
arraysbashifs

Bash: Using IFS to join an array into a string


Can someone explain what's going on here. All of this is executed consecutively in the same shell.

$ array=(a b c)
$ echo "${array[*]}"
a b c

So far so good.

$ IFS=/ echo "${array[*]}"
a b c

That's ok, the expansion happened before the whole line got executed.

$ IFS=/ x="${array[*]}"
$ echo $x
a b c

Same here, the expansion happened first, and x got that value.

$ echo "${array[*]}"
a/b/c

But ${array[*]} got changed, and the change is permanent.

$ x="${array[*]}"
$ echo $x
a b c

Ok, this is normal, I think - the original, default IFS value was used to expand the array variable in this assignment.

$ echo "${array[*]}"
a/b/c
$ 

But this totally doesn't make sense to me. First, the default IFS is not used here. Second, the assignment x="${array[*]}" didn't affect the value of ${array[*]} the same way it did before, in IFS=/ x="${array[*]}".


Solution

  • When you use:

    IFS=/ echo "${array[*]}"
    

    Then IFS is set local to the echo command (although not used by echo)

    When you use:

    IFS=/ x="${array[*]}"
    

    Then these are two separated variable assignment, one for IFS and one for x, so the IFS is now permanently changed to / as @jaypal mentioned.

    When you use:

    $ echo "${array[*]}"
    

    Then - when quoted - the first character of IFS is used as an output field separator with expansion of the array

    If it is unquoted, then it produces space separated fields:

    $ echo ${array[*]}
    

    Also, when you would use:

    $ echo "${array[@]}"
    

    Then each array element is expanded to a separate word, so the output field separator is not used so it becomes a single space..