9

I have set the IFS to x, i.e IFS=x. Now if I check the value of IFS, then it appears to be empty if I do not use double-quotes:

~ $ echo $IFS | cat -e
$
~ $ echo "$IFS" | cat -e
x$
~ $ echo $HOME   
/home/mar
~ $ echo "$HOME"
/home/mar
~ $ 

As seen above, $HOME does not behave like that. What is the reason for such behavior?

Martin
  • 7,516

3 Answers3

9

After the variable is expanded, word-splitting occurs and it gets split into empty word(s). Splitting is done using each character of the IFS variable as delimiter and since $IFS only expands to characters in the IFS it gets split into empty word(s).

So, for example:

IFS=xxx;
printf %q $IFS
''''''[root@localhost ~]#

And if you double quote, you are telling bash to treat everything inside the quotes as one word:

printf %q "$IFS"
xxx[root@localhost ~]#
taliezin
  • 9,275
  • As I understand, if I use single- or double-quotes around the argument for echo, then there is no word-splitting and this single argument is passed to echo. So am I correct that if I don't use double-quotes around the variable name then word-splitting based on characters in IFS variable take place? – Martin Jun 16 '15 at 07:19
  • You are correct, but not single quotes, if you use single quotes: echo '$IFS' result will be $IFS. – taliezin Jun 16 '15 at 07:26
  • I see, thanks! However, how should one understand word-splitting? I mean if I execute examples like IFS="blah" echo $IFS or IFS=x VAR="abcxklm" echo $VAR or IFS=x VAR="abcx" echo $VAR | sed -n l then I would think that word-splitting is substituting characters in expanded variable with space if IFS character(s) is in the middle of the string and with nothing if no other characters follow? – Martin Jun 16 '15 at 08:36
  • you can test simple word-splitting with this: list="koko moko" and then for i in $list and for i in "$list" will produce different results. – taliezin Jun 16 '15 at 09:07
4

I guess it's related to what's stated in Advanced Bash-Scripting Guide

Use double quotes to prevent word splitting. [2] An argument enclosed in double quotes presents itself as a single word, even if it contains whitespace separators.

With the examples (5.1):

var="'(]\\{}\$\""
echo $var        # '(]\{}$"
echo "$var"      # '(]\{}$"     Doesn't make a difference.

IFS='\'
echo $var        # '(] {}$"     \ converted to space. Why?
echo "$var"      # '(]\{}$"
fredtantini
  • 4,233
  • The reason why "" becomes " " is explained in http://unix.stackexchange.com/a/209184/27616 (by @StéphaneChazelas ) ( "" became an IFS, an Input Field Separator, so $var now contains 2 "parts", one before "", the other after "". And those 2 parts are written one after the other, separated by a space – Olivier Dulac Jun 15 '15 at 15:34
0

Another way to work around the word splitting issue here is:

set | grep -w IFS=

which outputs the default IFS as

IFS=$' \t\n'

See this related post on Stack Overflow: