On Sun, Jan 12, 2025 at 8:24 AM Félix Hauri <fe...@f-hauri.ch> wrote:

> Le Sat, Jan 11, 2025 at 10:49:50AM -0500, Greg Wooledge a écrit :
> > https://mywiki.wooledge.org/BashPitfalls#pf47
> > "It's a feature."
> >
>  -- how do we work around this nonsense?
>
> I've alredy noticed this, but never stictly tested them as:
>
>    for row in k{:v1{:v2{:{:{:,},},},:{:{:,},},},:{:{:,},},}; do
>        IFS=: read k v <<<"$row";
>        printf "%-20s %s\n" "row='$row'" "k='$k', v='$v'";
>    done
>    row='k:v1:v2:::'     k='k', v='v1:v2:::'
>    row='k:v1:v2::'      k='k', v='v1:v2::'
>    row='k:v1:v2:'       k='k', v='v1:v2:'
>    row='k:v1:v2'        k='k', v='v1:v2'
>    row='k:v1:::'        k='k', v='v1:::'
>    row='k:v1::'         k='k', v='v1::'
>    row='k:v1:'          k='k', v='v1'
>    row='k:v1'           k='k', v='v1'
>    row='k:::'           k='k', v='::'
>    row='k::'            k='k', v=''
>    row='k:'             k='k', v=''
>    row='k'              k='k', v=''
>
> Thanks for driving my attention to this *feature*!
>
> --
>  Félix Hauri  -  <fe...@f-hauri.ch>  -  http://www.f-hauri.ch
>
> Greg's link provides a workaround:

$ input='foo:bar:'
$ echo "$input:" | { IFS=: read -r f1 rest; rest=${rest%:}; declare -p
rest; }
declare -- rest="bar:"

However it only works for reading a single line. If you want to read a
file, I think `sed` might be worthwhile instead of doing this individually
for every line in a loop.

Here is a `sed` version:

delim=,
{
    sed -r -e "s/\$/$delim/" |
    while IFS="$delim" read -r k values; do
        values="${values%$delim}"
        echo "k='$k' v='$values'"
    done
} <<EOT
a,b,c,d,e
a,b,c,d,
a,b,c,d
a,b,c,
a,b,c
a,b,
a,b
a,
a
EOT

And here is a version you would have to use without `sed` to get the line
first, before you can append the field terminator to it:

delim=,
{
    while IFS= read -r row; do
        IFS="$delim" read -r k values < <(echo "$row$delim")
        values="${values%$delim}"
        printf "%-20s %s\n" "row='$row'" "k='$k' v='$values'"
    done
} <<EOT
a,b,c,d,e
a,b,c,d,
a,b,c,d
a,b,c,
a,b,c
a,b,
a,b
a,
a
EOT

Reply via email to