read stdin into variable?
Harald van Dijk
harald at gigawatt.nl
Sun Nov 8 21:41:51 UTC 2020
On 08/11/2020 20:18, Hadrien Lacour wrote:
> On Sun, Nov 08, 2020 at 09:12:13PM +0100, chiasa.men wrote:
>> Ahoy,
>>
>> how to get the following idiom ash-like translated? (I just called busybox on
>> my raspbian buster)
>>
>>
>> echo '12 34' | read a b ; echo "'${a}''${b}'"
>> ''''
>>
>> Doesnt the manual state that "The read utility shall read a single logical
>> line from standard input into one or more shell variables."
>> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html
>>
>> IFS
>> Determine the internal field separators used to delimit fields; see Shell
>> Variables.
>>
>> And
>> The shell shall set IFS to <space> <tab> <newline> when it is invoked.
>>
>
> Per POSIX (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12),
> commands in a pipeline all run in their own subshell unless your shell has an
> extension to circumvent this. So read won't affect the environment outside the
> pipeline.
For the avoidance of doubt, they mean here that such an extension is
permissible, if shells want to implement that it's fine, even in a
default mode. Some POSIX-conforming shells do that. Portable scripts can
neither assume that commands in a pipeline are, nor that they are not,
executed in a subshell environment. busybox could add this, if wanted,
as part of the many bash extensions it already adds to ash.
It is difficult to implement correctly in a way that plays nicely with
job control though, and I do not know of any shell that has tried to
make that work. In bash, the pipeline behaviour is controlled by the
lastpipe option, except that because of this issue the lastpipe option
is simply ignored when job control is active. Oversimplified, that means
it works in scripts but not in interactive mode.
> The usual way to solve this is:
>> read a b <<EOF
> $(echo 12 34)
> EOF
>> echo "$a" "$b"
There are two good workarounds. One is yours, which ensures read a b is
not executed in a subshell environment. Depending on the use case,
another good alternative is
echo 12 34 | {
read a b
echo "'${a}''${b}'"
}
This still executes `read a b` in a subshell environment, but lets the
following commands that use $a and $b also execute in that same subshell
environment. This workaround can be used when the following commands do
not need to read from the original stdin.
Cheers,
Harald van Dijk
More information about the busybox
mailing list