tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: sh read on files missing the final newline
Date: Mon, 6 Jul 2026 18:27:01 +0200
From: Edgar Fu�<ef%math.uni-bonn.de@localhost>
Message-ID: <akvXVSX/fA6CsV4J%trav.math.uni-bonn.de@localhost>
| I stumbled over the fact that sh's read returned 1 on the final part
| (call it a line or not) of a file when it didn't end in a newline.
I think there have been enough pointers to where the POSIX spec defines
lines and text files, so no more of that.
But the sh read built-in doesn't actually require either, though it would
have done back in SUS days (it does still call what is read a "logical line"
though, but the only definition of that is that it is a single record
read by the read command).
What it is defined to do is to read bytes until it finds the specified
delimiter byte, for which the default is '\n' - and if while doing
that it reaches EOF (ie: the delimiter is not found) the exit status
from read will (eventually) be 1.
Once it has done that, all data read (not counting the delimiter char)
will be split amongst the variables, using approximately the same method
field splitting of variable (etc) expansions uses on command lines
(approximately as read stops splitting once it has made enough fields
for the first N-1 variables (where N is the number of vars given to the
read command) and then just assigns whatever is left (with just leading
and trailing ISP-whitespace deleted) to the N'th (last) variable.
This happens (or should happen) even if read encountered EOF looking
for the delimiter.
Any variables not assigned a value from the field splitting are assigned
"" as their value.
The '\n' character is only relevant if it is the delimiter (or no delimiter
is specified, as it is the default), or if -r is not given, and the sequence
backslash-newline appears in the input, in which case if a different delim
wasn't specified, the backslash-newline pair are simply deleted. If there
is a different delim, some shells will delete a \-delim pair instead of
a \-newline pair (the standard allows both behaviours). Anything deleted
this way will be deleted before the delimiter check.
kre
ps: if the input to read contains any \0 chars, and the delimiter is not \0,
then very odd things are likely to happen, \0's cannot be stored in shell
vars (which applies to the data read) and since IFS is a shell var, cannot
be a field terminator either. Using \0 as the delimiter (-d '') however
works without issues, though generally you'd always use -r when doing that.
Home |
Main Index |
Thread Index |
Old Index