Whenever I read about IFS it was always in the context of read
(or at least thus I understood).
Is IFS used for anything else than read
shell-builtin?
Whenever I read about IFS it was always in the context of read
(or at least thus I understood).
Is IFS used for anything else than read
shell-builtin?
The POSIX shell manual has the following to say about field splitting:
After parameter expansion (Parameter Expansion), command substitution (Command Substitution), and arithmetic expansion (Arithmetic Expansion), the shell shall scan the results of expansions and substitutions that did not occur in double-quotes for field splitting and multiple fields can result.
The shell shall treat each character of the IFS as a delimiter and use the delimiters as field terminators to split the results of parameter expansion, command substitution, and arithmetic expansion into fields.
If the value of IFS is a
<space>
,<tab>
, and<newline>
, or if it is unset, any sequence of<space>
,<tab>
, or<newline>
characters at the beginning or end of the input shall be ignored and any sequence of those characters within the input shall delimit a field. For example, the input:
<newline><space><tab>foo<tab><tab>bar<space>
yields two fields, foo and bar.
If the value of IFS is null, no field splitting shall be performed.
Otherwise, the following rules shall be applied in sequence. The term " IFS white space" is used to mean any sequence (zero or more instances) of white-space characters that are in the IFS value (for example, if IFS contains
<space>
/<comma>
/<tab>
, any sequence of<space>
and<tab>
characters is considered IFS white space).IFS white space shall be ignored at the beginning and end of the input.
Each occurrence in the input of an IFS character that is not IFS white space, along with any adjacent IFS white space, shall delimit a field, as described previously.
Non-zero-length IFS white space shall delimit a field.
So any time the shell expands an unquoted parameter, command substitution, or arithmetic expansion it will split the result into fields based on how IFS is set.
You can see this in the context of parameter expansion with the following:
$ IFS=$' \t\n'
$ var='foo:bar'
$ printf '<%s>\n' $var
<foo:bar>
$ IFS=:
$ printf '<%s>\n' $var
<foo>
<bar>
$ printf '<%s>\n' "$var"
<foo:bar>
$ set -- foo bar baz
$ echo "$*"
foo:bar:baz
$ IFS=$' \t\n'
$ echo "$*"
foo bar baz
$
printf '<%s>\n' $var
. Using echo
(which joins its arguments with spaces) combined with awk
(which splits on blanks or whitespace) confuses things IMO.
– Stéphane Chazelas
Mar 17 '21 at 17:07
read
(which for the record is a shell-builtin) has a special call for IFS, if I am not wrong about this. – variableexpander Mar 17 '21 at 12:26read
doesn't call any program either. By that logic,eval
andexec
also do the same thing. – muru Mar 17 '21 at 12:32