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,284
  • 40
  • 125
  • 208

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,085
  • 1
  • 34
  • 38
  • 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,153
  • 1
  • 14
  • 21
  • 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:

codeforester
  • 722
  • 2
  • 8
  • 23