Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is IFS not taken into account by echo when set on the same line?

Tags:

bash

In bash, why isn't this:

declare -a array=(a b c d e)
IFS=',' echo "${array[*]}"

the same as:

echo_wrapper()
{
    echo "$*"
}

declare -a array=(a b c d e)
IFS=',' echo_wrapper "${array[@]}"
like image 579
silel Avatar asked Oct 16 '25 11:10

silel


2 Answers

Expansion happens before variable assignments within a simple command. From the Bash manual:

When a simple command is executed, the shell performs the following expansions, assignments, and redirections, from left to right.

  1. The words that the parser has marked as variable assignments (those preceding the command name) and redirections are saved for later processing.
  2. The words that are not variable assignments or redirections are expanded (see Shell Expansions). If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments.
  3. Redirections are performed as described above (see Redirections).
  4. The text after the ‘=’ in each variable assignment undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal before being assigned to the variable.

Step 1 identifies your IFS assignment, but doesn't perform it. Step 2 expands "${array[*]}" using the existing value of IFS. Then step 4 changes the value of IFS.

Workaround, if you don't need to modify the process environment, working directory, etc.: use a subshell.

(IFS=, ; echo "${array[*]}")
like image 121
rob mayoff Avatar answered Oct 19 '25 02:10

rob mayoff


a different workaround

join () {
    local IFS=$1    # changes to IFS are localized to the function
    shift
    echo "$*"
}

join , "${array[@]}"
like image 43
glenn jackman Avatar answered Oct 19 '25 03:10

glenn jackman