2

I have problem with "IFS=$'\n'.

old_IFS=$IFS
file="Good morning
Good morning
Good morning
Good morning
Good morning"

IFS=$'\n'
for line in $file
    do
       echo $line
done
IFS=$old_IFS

When I execute the script:

Good mor
i
g
Good mor
i
g
Good mor
i
g
Good mor
i
g
Good mor
i
g

The "n" is deleted. I would like to view the files line by line

2 Answers2

2

The proper way to iterate over multi-line data (whether or not your shell supports $'...') is with a while loop that calls read repeatedly:

while read -r; do
    echo "$REPLY"
done <<EOF
$file
EOF
chepner
  • 497,756
  • 71
  • 530
  • 681
  • +1 Great to know. I'd note that `REPLY` is Bash variable not available in all shells. – John B May 27 '14 at 15:33
  • Right, I forgot to double-check that. If you are providing a specific variable to use in place of `REPLY`, you should also set `IFS` to the empty string to prevent word-splitting (which could drop any leading or trailing whitespace in the line): `IFS= read -r line`. – chepner May 27 '14 at 15:48
1

As others have pointed out, I don't think the shell you're using supports $'...' syntax.

If your system is using Dash as sh, you should be able to assign IFS to a new line by assigning it to an empty or unassigned variable. For example, n=""; IFS=$n would allow you to split by new lines. This is a hack, and only works because an empty variable is interpreted as a new line to the interpreter.

You could also read from a here string in shells like Bash, using <<<word.

file="Good morning
Good morning
Good morning
Good morning
Good morning"

while read line; do
    echo $line
done <<<"$file"

Otherwise, you can just read from a file line by line.

while read -r line; do 
    echo "$line"
done < file
John B
  • 3,566
  • 1
  • 16
  • 20
  • That won't work, but you can easily set `IFS` to a literal newline by putting it in quotes. So `IFS='` on one line and a lone `'` on the next line. (Sorry, no code formatting in comments.) – tripleee May 26 '14 at 16:59
  • Also the unquoted `$line` is still problematic because it is subject to wildcard expansion; you need to use `"$line"`. – tripleee May 26 '14 at 17:00
  • No problem, please see my updated post for some further explanation. – John B May 27 '14 at 15:23
  • ...might even make it `while IFS= read -r line; do echo "$line"; done – Charles Duffy May 27 '14 at 15:42