[bash] the <<<$DATA issue

[bash] the <<<$DATA issue

am 11.01.2008 18:06:28 von guisep4

When I need to modify vars inside while loop, I try to use <<<$DATA
instead of follows.

Generally, the following two forms are expected to be equivalent,
no ?:

1) while read x; do ... ; done 2) DATA="`cat
Except for the case when file is empty. Then 2nd form does not work
right for me:
a)
while read x; do echo "<>"; done # correct: does not print anything
b)
DATA="`cat >" ; done
<<<"$DATA"
# wrong: prints <<>> once

Why second form enters the loop once in (b) ? Is it a bash bug ?

Thanks
G.G.

Re: [bash] the <<<$DATA issue

am 11.01.2008 20:17:04 von Stephane CHAZELAS

On Fri, 11 Jan 2008 09:06:28 -0800 (PST), guisep4@gmail.com wrote:
> When I need to modify vars inside while loop, I try to use <<<$DATA
> instead of > follows.
>
> Generally, the following two forms are expected to be equivalent,
> no ?:
>
> 1) while read x; do ... ; done > 2) DATA="`cat >
> Except for the case when file is empty. Then 2nd form does not work
> right for me:
> a)
> while read x; do echo "<>"; done > # correct: does not print anything
> b)
> DATA="`cat >" ; done
> <<<"$DATA"
> # wrong: prints <<>> once
>
> Why second form enters the loop once in (b) ? Is it a bash bug ?
[...]

because otherwise

read foo <<< bar

wouldn't put anything into $foo.

The cmd <<< xxx syntax (that comes from the "rc" shell, through
zsh), stores "xxx" followed by a NL character into a temporary
file and opens that file for reading as the standard input of
cmd.

$ od -c <<< ''
0000000 \n
0000001

The thing is that for non-empty files,

foo=`cat < file`

removes the trailing NLs (yes all of them, however strange and
inapropriate that may seem), and <<< restores one.

For an empty file, there's no NL that `...` may remove and <<<
adds one nonetheless.

You could do instead:

data=`cat < "$file"; echo .`; data=${data%.}
# that stores the content of the file exactly as long as it
# doesn't contain NUL bytes (except for zsh that supports NUL
# bytes.

and then:

printf %s "$data" | {
while IFS= read -r line; do
printf '<<%s>>\n' "$line";
done
if [ -n "$line" ]; then
printf 'There was something after the last NL: <<%s>>\n' "$line"
fi
}

Another illustration of why you should avoid "while read" loops.

--
Stephane

Re: [bash] the <<<$DATA issue

am 11.01.2008 20:26:32 von Stephane CHAZELAS

On 11 Jan 2008 19:17:04 GMT, Stephane Chazelas wrote:
[...]
>> 2) DATA="`cat [...]
>> Why second form enters the loop once in (b) ? Is it a bash bug ?
> [...]
>
> because otherwise
>
> read foo <<< bar
>
> wouldn't put anything into $foo.
[...]

Well, it would put "bar" in $foo, but would return false because
it didn't manage to read a full line (that is, up to the
terminating NL).

--
Stephane