Mailinglist Archive: opensuse (1318 mails)
| < Previous | Next > |
Re: [opensuse] BASH - while read; howto read last line in file without blank line at end?
- From: David Bolt <bcrafhfr@xxxxxxxxxx>
- Date: Sat, 1 Nov 2008 12:58:19 +0000
- Message-id: <7lAMi4arJFDJFwzq@xxxxxxxxxxxxxxxxxxx>
On Sat, 1 Nov 2008, Sandy Drobic wrote:-
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.
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_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
line_one -> has_EOL
line_two -> has_EOL
line_three -> has_EOL
davjam@playing:~>
Okay, it's still missing the last line. Last try, and I've split this
one up so it's spread over a few lines to make it easier to read, with
one that will work and should even handle 0-length files:
davjam@playing:~> while :
line_two -> has_EOL
line_three -> has_EOL
line_four -> no_EOL
davjam@playing:~>
With this one, the echo command is executed only if ${LINE} and/or
${TEXT} have any contents. I assigned the return value from the read
command and use that after the echo command to decide whether to break
out of the loop. This avoids printing out:
->
if there's a blank line in the input file.
Of course, you could add another line:
[ -z "${LINE}${TEXT}" ] && echo
to show there was a blank line present.
Regards,
David Bolt
--
Team Acorn: http://www.distributed.net/ RC5-72 @ ~70Mkeys/s
SUSE 10.1 32 | | openSUSE 10.3 32b | openSUSE 11.0 32b
| openSUSE 10.2 64b | openSUSE 10.3 64b | openSUSE 11.0 64b
RISC OS 3.6 | TOS 4.02 | openSUSE 10.3 PPC | RISC OS 3.11
--
To unsubscribe, e-mail: opensuse+unsubscribe@xxxxxxxxxxxx
For additional commands, e-mail: opensuse+help@xxxxxxxxxxxx
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.
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"
| \
while read LINE TEXT ; do echo "${LINE} -> ${TEXT}" ; doneline_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.txtdavjam@playing:~> while read LINE TEXT ; do echo "${LINE} -> ${TEXT}" ; done
<dummy.txt
line_one -> has_EOL
line_two -> has_EOL
line_three -> has_EOL
davjam@playing:~>
Okay, it's still missing the last line. Last try, and I've split this
one up so it's spread over a few lines to make it easier to read, with
one that will work and should even handle 0-length files:
davjam@playing:~> while :
doline_one -> has_EOL
read LINE TEXT
EXIT="$?"
[ -n "${LINE}${TEXT}" ] && echo "${LINE} -> ${TEXT}"
[ "${EXIT}" -ne 0 ] && break
done <dummy.txt
line_two -> has_EOL
line_three -> has_EOL
line_four -> no_EOL
davjam@playing:~>
With this one, the echo command is executed only if ${LINE} and/or
${TEXT} have any contents. I assigned the return value from the read
command and use that after the echo command to decide whether to break
out of the loop. This avoids printing out:
->
if there's a blank line in the input file.
Of course, you could add another line:
[ -z "${LINE}${TEXT}" ] && echo
to show there was a blank line present.
Regards,
David Bolt
--
Team Acorn: http://www.distributed.net/ RC5-72 @ ~70Mkeys/s
SUSE 10.1 32 | | openSUSE 10.3 32b | openSUSE 11.0 32b
| openSUSE 10.2 64b | openSUSE 10.3 64b | openSUSE 11.0 64b
RISC OS 3.6 | TOS 4.02 | openSUSE 10.3 PPC | RISC OS 3.11
--
To unsubscribe, e-mail: opensuse+unsubscribe@xxxxxxxxxxxx
For additional commands, e-mail: opensuse+help@xxxxxxxxxxxx
| < Previous | Next > |