0
$ IFS=";"

$ read first second 
i am;a_i b c
$ echo $first
i am
$ echo $second
a_i b c

$ echo $IFS
  1. Am I right that read first second is a subprocess of the current shell process? If yes, why don't we need export IFS=";"?
  2. why is IFS empty?
Tim
  • 101,790

4 Answers4

5

Am I right that read first second is a subprocess of the current shell process? If yes, why don't we need export IFS=";"?

No, read is a bash bultin function. No subshell or subprocess is created here, so we don't need to export IFS.

why is IFS empty?

Because you don't use double quote. You have changed value IFS to ;, so when you echo $IFS, after $IFS is expanded to ;, the shell performs word spliting and globbing, with ; as separator. So nothing is printed.

Try:

$ IFS=";"
$ printf "%s\n" $IFS

$ printf "%s\n" "$IFS"
;

Note

cuonglm
  • 153,898
  • Thanks. (1) if read is not a builtin, will I have to export IFS=";"? (2) why do I need double quote for $IFS? Why can i echo $a, if replacing IFS with a? – Tim Aug 30 '14 at 21:38
  • @Tim: (1) Yes. (2) Because you have changed value IFS to ;, so when you echo $IFS, after $IFS is expanded to ;, the shell performs spliting fields and globbing, with ; as separator. So nothing is printed. – cuonglm Aug 30 '14 at 21:51
  • The answers at that link are not very good. – mikeserv Aug 31 '14 at 02:49
  • Depending on the shell, echo $IFS will output NL (where $IFS is a field delimiter (bash, some implementations/versions of ksh or dash) or non-whitespace are not considered different from whitespace (Bourne)) as it's like echo ''. And with others (where $IFS is a field separator (zsh, yash, some versions/implementations of dash or ksh), it will output SPC NL as it's like echo '' '' – Stéphane Chazelas Sep 01 '14 at 17:25
1

If we type type read we get read is a shell builtin. Therefore it is not run as a sub-process.

1

In answer to why IFS is empty. It is not. But the value in IFS is changing the behaviour of the shell. Below is not an explanation but just the result of my experiments using bash on Debian Gnu+Linux.

a=";"; echo $a produces ;.

IFS=";"; echo $IFS produces blank line. IFS=";"; echo "$IFS" produces ;.

Now a=";"; echo $a produces blank line, but IFS=" "; a=";"; echo $a produces ; again.

So

Now IFS=";"; a=";"; echo $a produces blank line, but IFS=" "; a=";"; echo $a produces ;.

Therefore the value of IFS changes the behaviour (then quotes not used in echo).

1
IFS=\;; set -- $IFS; echo $#; echo "$*"

1
;

IFS=; set -- $IFS; echo $#; echo "$*"

0
#there doesn't seem to be anything here

As you can see - $IFS is not empty in the first case - it contains exactly one field separator.

When the shell expands an unquoted variable it splits its value on the delimiters defined in $IFS. In this way each variable is, potentially, an $IFS separated array. By default $IFS is set to a <space>, a \tab, and a \newline. Each of these has special qualities in $IFS as they are $IFS whitespace. $IFS whitespace delimiters are not retained and each sequence of either is instead truncated to a single field when the shell performs the wordsplitting, whereas all others will delimit a single field per separator. $IFS whitespace will also be removed entirely from either the beginning or end of a field. For instance:

IFS=/; slashes=///////; printf '<%s>' $slashes
<><><><><><><>

IFS=' '; spaces='      '; printf '<%s>' $spaces
<>

printf '<%s>' $spaces$slashes
<///////>

But $IFS whitespace is obviously not removed when it is not in $IFS:

IFS=/; printf '<%s>' $spaces$slashes
<      ><><><><><><>
mikeserv
  • 58,310