bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: document that read built-in can't return zero-length string in the m


From: Martin D Kealey
Subject: Re: document that read built-in can't return zero-length string in the middle of input
Date: Sun, 14 Jan 2024 00:27:23 +1000

Random irreversible behaviour change strikes again.

This changed in Bash 4.3.0, and to make matters worse, shopt -s compat42
does not restore the previous behaviour.

Up to Bash 4.2, read -N1 would indeed set the receiving variable to empty
while returning a zero status, having read only one byte.

> $ printf 'a\0b' | bash_4.2.9p1-release -c 'for i in 0 1 2 ; do read -N1
c[i] ; s[i]=$? ; done ; declare -p c s'
> declare -a c='([0]="a" [1]="" [2]="b")'
> declare -a s='([0]="0" [1]="0" [2]="0")'

>From Bash 4.3 onwards the behaviour reported by the OP is observed:

> $ printf 'a\0b' | bash_4.3.0p52-release -c 'shopt -s compat42 ; for i in
0 1 2 ; do read -N1 c[i] ; s[i]=$? ; done ; declare -p c s'
> declare -a c='([0]="a" [1]="b" [2]="")'
> declare -a s='([0]="0" [1]="0" [2]="1")'

I had already suspected this was the case, since Xterm mouse tracking would
get glitchy in large windows. (In mouse tracking mode, Xterm will report
the mouse position as ESC [ M c1 c2 c3,  where c1, c2 & c3 are single bytes
encoding the button state, column, and row, each as the value plus 32. So
when the mouse is over column 224 of an Xterm, the column is reported by
sending a NUL byte. If that byte is discarded, the following input byte
could mistakenly be consumed as part of the mouse-position escape sequence;
if it's the ESC that starts the next sequence, things go horribly wrong.)

I "fixed" the issue for me by:
(a) not writing anything beyond column 223, and
(b) rotating my screen to portrait mode, so that a full-screen Xterm is 179
columns and 147 lines.

Oh wait, if I switch to "tiny" font, I get 239 lines. Dang.

-Martin


On Fri, 12 Jan 2024 at 11:02, Greg Wooledge <greg@wooledge.org> wrote:

> On Fri, Jan 12, 2024 at 01:29:19AM +0100, Ángel wrote:
> > One might say "reading exactly nchars characters into the name",
>
> I would still find that confusing.  What actually counts is how many
> characters are *stored* in the variable, not how many characters are
> *read* from the input.
>
> > but
> > given that there's no mention that the NULs are never stored in
> > variables, I would tend to add a line below saying e.g. "NUL characters
> > cannot be stored in bash variables and are always ignored by read".
>
> I would be as explicit as possible.  Don't require the reader to put
> any pieces together themselves.
>
> How about this for the man page:
>
>     -N nchars
>         read returns after storing exactly nchars characters in the
>         first named variable (or REPLY if no variable is named), unless
>         EOF is encountered or read times out.  read does not wait for
>         a complete line of input; any delimiter characters encountered
>         in the input are not treated specially, and do not cause read to
>         return before storing nchars characters.  NUL characters are
>         ignored, as they cannot be stored in variables.  The result is
>         not split on the characters in IFS; the intent is that the
>         variable is assigned exactly the characters read (with the
>         exceptions of NUL and backslash; see the -r option below).  If
>         multiple variable names are given, input is only stored in the
>         first; all other variables will be empty.
>
> And this for the help text:
>
>     -N nchars  return only after storing exactly NCHARS characters, unless
>                EOF is encountered or read times out, ignoring any NUL or
>                delimiter characters
>
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]