Greg Wooledge wrote in
 <20250112215505.gb27...@wooledge.org>:
 |On Sun, Jan 12, 2025 at 16:26:04 -0500, Chet Ramey wrote:
 |>> In this case, we get the "expected" result:
 |> 
 |> You just restated the original example while ignoring the part of my
 |> message about looking for additional input after you find a delimiter.
 |
 |Right.  You explained why it works the way it does.  But from a user's
 |point of view, it's just unexpected behavior.
 |
 |I'm not asking for anything to be changed, because I know that's not an
 |option.  All I can do at this point is try to make sure people are
 |aware that the read command has this behavior, and that they should
 |plan around it.
 |
 |If one is reading a CSV file, then there are approprate tools that can
 |be used.  This part has been covered.
 |
 |However, a common reason someone uses "IFS=: read -r var1 rest"
 |is because they're reading a text file/stream in which each line has
 |a delimited field, followed by a delimiter, followed by a bunch of
 |unpredictable free text.  Maybe it's a filename, or a description, or
 |something a user typed.
 |
 |If one wants everything after the delimiter to be stored in the "rest"
 |variable *without modification*, the read command shown above won't
 |do the job.  It modifies the line in a very specific edge case, which
 |one's testing probably won't encounter.
 |
 |That's the pitfall.
 |
 |As a workaround, one may append an extra delimiter to the line, then
 |do the read, then strip the added delimiter.  That's on the wiki page.
 |
 |Or, one may read the entire line without field splitting it at all,
 |and then use ${line%%:*} and ${line#*:} to split it.

Btw my MUA (will) support(s) (with the next release) storing in "a
result set" (that i "invented" because i needed a mechanism
exactly like $*/$@/$#/$1.. etc, but alongside, for example for
storing result matches of regular expressions of if etc).

  printf 'ab,cd,ef,\nab,ef,\nab,cd,ef,,,x,y,z\n' |
  s-nail -R:/ -Snoheader \
    -Y 'set ifs=,; read field1 rest; unset ifs; var field1 rest' \
    -Y 'set ifs=,; read field1 rest; unset ifs; var field1 rest' \
    -Y 'set ifs=,; read ^; unset ifs; var ^# ^0 ^1 ^2 ^*' \
    -Yxit
  s-nail version v14.9.25-636-gc7c14cee09-dirty.  Type `?' for help
  set field1=ab
  set rest=cd,ef,
  set field1=ab
  set rest=ef
  #^#=8
  #^0=16
  #^1=ab
  #^2=cd
  #^*='ab cd ef   x y z'

Should be doable for bash in the "no-argument" case, which
currently works though POSIX requires at least one argument:

  $ </dev/null dash -c 'read'
  dash: 1: read: arg count

  $ </dev/null bash -c 'read'

  $ prt-get info bash
  Name:         bash
  Path:         /usr/ports/core
  Version:      5.2.37
  Release:      1
  Description:  An sh-compatible command language interpreter
  URL:          https://tiswww.case.edu/php/chet/bash/bashtop.html
  Maintainer:   CRUX System Team, core-ports at crux dot nu
  Dependencies: readline

Busybox sh has the same bug.
Ie, like $BASH_REMATCH, $BASH_READFIELDS or so.

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)
|
|In Fall and Winter, feel "The Dropbear Bard"s pint(er).
|
|The banded bear
|without a care,
|Banged on himself for e'er and e'er
|
|Farewell, dear collar bear

Reply via email to