Re: builtin read stops at '\0'
On Wed, May 18, 2011 at 02:10:39PM +0200, Rafaël Fourquet wrote: > If a line containing the '\0' is read into a variable, the content > of this variable does not contain the part after the '\0' character. > > Repeat-By: > echo -e 'a\0b' | (read f; echo $f) > > The output is 'a', and '\0b' is stripped. Bash stores strings the same way C does. NUL marks the end of a string. So, even if f does contain a\0b, any attempt to retrieve the value of f is going to stop at the NUL byte. If you want to handle a stream of NUL-delimited strings in bash, the best approach is to use read -d '', thus: imadev:~$ printf '%s\0' one two three | while read -r -d '' s; do echo "<$s>"; done read -d '' means "stop at NUL, instead of stopping at newline".
Re: builtin read stops at '\0'
> > > If you want to handle a stream of NUL-delimited strings in bash, the > best approach is to use read -d '', thus: > > imadev:~$ printf '%s\0' one two three | while read -r -d '' s; do echo > "<$s>"; done > > > > > read -d '' means "stop at NUL, instead of stopping at newline". > Thanks for your reply. I was aware of your solution, but in my situation the '\0' problem makes things more complicated: I have a program which outputs groups of filenames. Each group is separated by a newline, and within each group, each name is separated by '\0'. I want to pipe each group to xargs -0. But because of this '\0' implementation detail (I did not find it is documented). the following solution (working in zsh) don't work in bash (and I couldn't find a non-convoluted solution in bash) : myprog | while read group; do echo $group | tr -d '\n' | xargs -0 ls -1; done If I use , I don't know how to break on each line... A solution with mapfile would be even better, but mapfile has the same problem as read in this regard.
Re: builtin read stops at '\0'
On Thu, May 19, 2011 at 03:23:55PM +0200, Rafaël Fourquet wrote: > I have a program which outputs groups of filenames. Each group is separated > by a newline, and within each group, > each name is separated by '\0'. That seems backwards somehow... the "stronger" delimiter (NUL) is used in the inner group, and the "weaker" delimiter (newline) in the outer. Oh well -- I assume you have no control over that. Here's what I'd do: just use tr to swap the delimiters. while read -d '' -r group; do mapfile -t files <<< "$group" ... done < <(tr '\n\0' '\0\n' < "yourfile") > I want to pipe each group to xargs -0. Not what I'd do.
Re: builtin read stops at '\0'
> > Here's what I'd do: just use tr to swap the delimiters. > > while read -d '' -r group; do > mapfile -t files <<< "$group" > ... > done < <(tr '\n\0' '\0\n' < "yourfile") > > > I want to pipe each group to xargs -0. > > Not what I'd do. > Thanks! But is there something wrong with xargs? or is it my use of "echo ...|xargs" (I did not know "here strings") Do you mean, in your example, that e.g. ... do mapfile -t files <<< "$group" ; ls -1 "${files[@]}"; done ... is better than: ... do xargs -d '\n' ls -1 <<<"$group"; done ...
Re: builtin read stops at '\0'
On Thu, May 19, 2011 at 04:30:40PM +0200, Rafaël Fourquet wrote: > Do you mean, in your example, that e.g. > ... do mapfile -t files <<< "$group" ; ls -1 "${files[@]}"; done ... > is better than: > ... do xargs -d '\n' ls -1 <<<"$group"; done ... imadev:~$ group=$'foo\nbar\n"hi mom"\n' imadev:~$ xargs -d '\n' printf '<%s> ' <<< "$group" xargs: unknown option: -d Must be some GNUism you're attempting to use (granted, the -0 was also a GNUism, but it's at least one I've heard of -- and is also present on most BSD boxes). If my guess is correct, your -d option is supposed to turn off the blatant historical stupidity and uselessness that characterize xargs: imadev:~$ xargs printf '<%s> ' <<< "$group" imadev:~$ Where'd the quotes go?? Oh, right, xargs eats them! imadev:~$ group=$'foo\nbar\n"hi mom"three quotes"\n' imadev:~$ xargs printf '<%s> ' <<< "$group" xargs: missing quote?: quotes So, apart from "xargs doesn't have a -d option" and "xargs without a -d option can't handle filenames", sure, xargs is awesome!
Re: Feature Request - Allow mapfile to handle NUL-delimited data
On 13 May 2011, at 20:07, DJ Mills wrote: > A -0 option, or even an option to use a different field separator, would be > an > excellent feature for mapfile. Currently, of course, you can use: > > while IFS= read -rd '' file; do array+=("$file"); done > > mapfile is considerably faster, however, and I think this would be quite > handy. seconded. I'm not sure why it only works for lines. Sure, on the shell data is often line-based, but more often than that, line-based parsing is bad and should be done with a safe delimiter rather than \n instead.
Re: Shell case statements
[adding bug-bash] On 05/16/2011 07:23 PM, Wayne Pollock wrote: > (While cleaning up the standard for case statement, consider that it is > currently > unspecified what should happen if an error occurs during the expansion of the > patterns; as expansions may have side-effects, when an error occurs on one > expansion, should the following patterns be expanded anyway? Does it depend > on > the error? It seems reasonable to me that any errors should immediately > terminate > the case statement.) Well, that's rather all over the place, but yes, it does seem like bash was the buggiest of the lot, compared to other shells. Interactively, I tested: readonly x=1 case 1 in $((x++)) ) echo hi1 ;; *) echo hi2; esac echo $x.$? bash 4.1 printed: bash: x: readonly variable hi1 1.0 which means it matched '1' to $((x++)) before reporting the failure assign to x, and the case statement succeeded. Changing the first "1" to any other string printed hi2 (the * case). zsh printed: zsh: read-only variable: x 1.0 which means it aborted the case statement before executing any clauses, but left $? at 0. ksh printed: ksh: x: is read only 1.1 which means that both the case statement was aborted, and $? was impacted. dash printed: dash: arithmetic expression: expecting primary: "x++" 1.2 so it was like ksh other than choice of error status. -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature