Search code examples
bashseparatorcarriage-returnlinefeed

Bash seems to convert LF into LFCR


It seems that Bash converts LF to LFCR. Indeed, here is an example bellow that describes that:

text=$(echo -e "foo\nbar\ntir")

When setting IFS to the LF end of line:

IFS=$(echo -e "\n")

the \n in the string text is not interpreted such as bellow:

for w in $text ; do echo ${w}';' ; done

Output:

foo
bar
tir;

Here the character ";" used as a marker shows that $text contains only one element and so \n is not interpreted although it was set as the IFS.

But now, while setting IFS to the LFCR end of line:

IFS=$(echo -e "\n\r")

the output of the previous command turns into:

foo;
bar;
tir;

The marker ";" shows that $text contains three elements and thereby \n in $text has been interpreted as a \n\r (LFCR) set as the IFS.

So, why does Bash seems convert LF to LFCR? If it does not, what is the underlying explanation please?


Solution

  • $IFS is actually being set to an empty string.

    $ IFS=$(echo -e "\n")
    $ echo "[$IFS]"
    []
    

    When $(...) captures output it removes trailing newlines. You can set $IFS to a newline by using $'...', shell syntax that interprets escape sequences while avoiding the trimming problem.

    $ IFS=$'\n'
    $ echo "[$IFS]"
    [
    ]
    $ text=$'foo\nbar\nbaz\n'
    $ printf '%s;\n' $text
    foo;
    bar;
    baz;