1

Consider this bash session:

set -- 1 2 3
echo "$*"          # 1 2 3  (as expected)
IFS=a echo "$*"    # 1 2 3  (why not "1a2a3"?)
IFS=a; echo "$*"   # 1a2a3a (as expected)

Try it online!

Why does the "assignment before command" syntax not work to set IFS to a different value for the duration of the single command? It appears you must change the value of IFS first with a separate command.

Cyrus
  • 84,225
  • 14
  • 89
  • 153
Jonah
  • 15,806
  • 22
  • 87
  • 161

1 Answers1

1

Because IFS affects the parsing (tokenization, word-splitting) of a command, so it must be set before that command is parsed. This is why IFS=a echo "$*" can only use the original IFS, not a.

It's a somewhat similar case to FOO=bar echo $FOO not echoing bar. $FOO is substituted (empty) and then the command, with it's variable assignment is executed.

Jens
  • 69,818
  • 15
  • 125
  • 179
  • Thanks. So the only way to reset it for one cmd is to save the old value, set to new value, execute cmd, then set back to old value, correct? – Jonah Sep 29 '19 at 17:50
  • @Jonah Correct, and you will find many scripts doing exactly that with `IFS` when they only temporarily need to use it. – Jens Sep 29 '19 at 17:52
  • It's either that, or scope it to a subshell, or do things a different way entirely (`printf -v outvar '%sa' "$@"; echo "${outvar%a}"`, f/e). – Charles Duffy Sep 29 '19 at 17:53
  • 1
    @Jonah: a subshell with its own environment might help: `set -- 1 2 3; (IFS=a; echo "$*"); echo "$IFS"` – Cyrus Sep 29 '19 at 17:53
  • Thanks @Cyrus, makes sense now. – Jonah Sep 29 '19 at 17:54