bug-bash
[Top][All Lists]
Advanced

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

Re: Option for read to handle incomplete last line


From: Greg Wooledge
Subject: Re: Option for read to handle incomplete last line
Date: Sun, 24 Oct 2021 09:42:11 -0400

On Sun, Oct 24, 2021 at 06:41:59PM +0900, Koichi Murase wrote:
> > my apologies if there's a much easier solution for the following
> > problem - in this case please let me know!
> 
> We can always define a shell function (which would work in all the
> POSIX shells):
> 
> read_line() { read line || test -n "$line"; }
> printf '%s' "$input" | while read_line; do printf '  %s\n'; done

You missed -r in your read command, and "$line" in your second printf.


For bash scripts using this, I'd go a little bit fancier:

read_line() {
  if (($# == 0)) || [[ ${!#} = -* ]]; then
    declare -n _rl_lastvar=REPLY
  else
    declare -n _rl_lastvar=${!#}
  fi
  read -r "$@" || test -n "$_rl_lastvar"
}


This gives us a lot more flexibility:

printf %s "$input" | while read_line; do printf '<%s>\n' "$REPLY"; done

printf %s "$input" | while read_line -e; do printf '<%s>\n' "$REPLY"; done

printf %s "$input" | while read_line -r line; do printf '<%s>\n' "$line"; done

printf 'foo bar\nbaz quux' | while read_line a b; do printf '<%s> <%s>\n' "$a" 
"$b"; done

printf 'foo&bar\nbaz&quux' | while IFS=\& read_line a b; do printf '<%s> 
<%s>\n' "$a" "$b"; done

printf 'foo\0bar\0baz' | while read_line -rd '' line; do printf '<%s>\n' 
"$line"; done

printf 'foo bar\nbaz quux' | while read_line -ra arr; do printf '<%s> ' 
"${arr[@]}"; echo; done


This intentionally skips a trailing incomplete line that has too few
fields, as in:

unicorn:~$ printf 'foo bar\nbaz' | while read_line a b; do printf '<%s> <%s>\n' 
"$a" "$b"; done
<foo> <bar>


The incomplete line here only has one field, so the "lastvar" (b) is
empty, and therefore the incomplete line isn't counted.  I consider
this a feature, but others may not.

Of course, it's still not perfect, as it won't handle cases like
read_line -t 5

But I refuse to try to write that.  The script-writer can simply change
it to   read_line -t 5 REPLY   or whatever alternative they want.



reply via email to

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