On Sat, 1 Nov 2008, Sandy Drobic wrote:-
David C. Rankin wrote:
Listmates,
I'm stumped on another simple BASH problem. How do I read the last line of a file with a while loop without requiring a blank line at the end of the file?
You can't, not if the loop-test is using the true/false return from read to work out whether to execute the loop body or not. Without an EOL, read will actually read the line and store it in the variables, but returns a false if there's no EOL which the 'while' then sees as a failure and so causes it to skip the body of the loop.
Simple example I'm stuck on:
{ while read alias url; do echo -e "${alias}\t${url}" done } < ~/linux/scripts/config/repos
Remove the curly brackets and everything runs fine on my system.
while read LINE TEXT ; do echo "${LINE} -> ${TEXT}" ; done
do read LINE TEXT EXIT="$?" [ -n "${LINE}${TEXT}" ] && echo "${LINE} -> ${TEXT}" [ "${EXIT}" -ne 0 ] && break done
Not here it doesn't, or at least not on 10.3 or 11.0. If you've used an
editor to create the file, it's possible that it's auto-added an EOL to
the last line. I know from experience that both nano and pico do,
whereas Kate/Kwrite don't.
Anyway, you can see the effect yourself by using printf, without using a
terminating '\n', to ensure there's no final EOL character. Something
like this gives an ample demonstration of the problem:
davjam@playing:~> printf "line_one\thas_EOL\nline_two\thas_EOL\nline_three\thas_EOL\nline_four\tno_EOL"
line_one has_EOL
line_two has_EOL
line_three has_EOL
line_four no_EOLdavjam@playing:~>
^^^^^^^^^^^^^^^^^
Shows there was no EOL character or this would have been on a new line.
Next, using the same printf and piping it into a loop:
davjam@playing:~> printf "line_one\thas_EOL\nline_two\thas_EOL\nline_three\thas_EOL\nline_four\tno_EOL" | \
line_one -> has_EOL
line_two -> has_EOL
line_three -> has_EOL
davjam@playing:~>
Nope, it's missing the last line. Just to make sure, lets try sending
the output of printf into a file and then using that:
davjam@playing:~> printf "line_one\thas_EOL\nline_two\thas_EOL\nline_three\thas_EOL\nline_four\tno_EOL" >dummy.txt
davjam@playing:~> while read LINE TEXT ; do echo "${LINE} -> ${TEXT}" ; done