Question

I was under the impression that setting IFS would change the delimiter that read uses when separating a line of text into fields, but clearly I'm missing something:

# OK: 'read' sees 3 items separated by spaces
$ (IFS=' '; x="aa bb cc"; echo "'$x'"; read a b c <<< $x;\
  echo "'$a' '$b' '$c'")
'aa bb cc'
'aa' 'bb' 'cc'

# OK: 'read' sees a single item after IFS is changed
$ (IFS=','; x="aa bb cc"; echo "'$x'"; read a b c <<< $x;\
  echo "'$a' '$b' '$c'")
'aa bb cc'
'aa bb cc' '' ''

# Why doesn't 'read' see 3 items?
$ (IFS=','; x="dd,ee,ff"; echo "'$x'"; read a b c <<< $x;\
  echo "'$a' '$b' '$c'")
'dd,ee,ff'
'dd ee ff' '' ''

# OK: 'read' sees a single item when IFS is restored.
$ (IFS=' '; x="dd,ee,ff"; echo "'$x'"; read a b c <<< $x;\
  echo "'$a' '$b' '$c'")
'dd,ee,ff'
'dd,ee,ff' '' ''

# OK: 'read' again sees 3 items separated by spaces.
$ (IFS=' '; x="gg hh ii"; echo "'$x'"; read a b c <<< $x;\
  echo "'$a' '$b' '$c'")
'gg hh ii'
'gg' 'hh' 'ii'

Why doesn't IFS=',' make read parse dd,ee,ff as three fields?

Was it helpful?

Solution

# Why doesn't 'read' see 3 items?
$ (IFS=','; x="dd,ee,ff"; echo "'$x'"; read a b c <<< $x;\
  echo "'$a' '$b' '$c'")
'dd,ee,ff'
'dd ee ff' '' ''

Because you don't quote your variables.

$ ( IFS=','; x="dd,ee,ff"; echo "'$x'"; read a b c <<< "$x";\
  echo "'$a' '$b' '$c'")
'dd,ee,ff'
'dd' 'ee' 'ff'

EDIT: When the variable isn't quoted, the expansion causes Word Splitting:

The shell scans the results of parameter expansion, command substitution, and arithmetic expansion that did not occur within double quotes for word splitting.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top