[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Scope change in loops with "read" built-in
From: |
Kerin Millar |
Subject: |
Re: Scope change in loops with "read" built-in |
Date: |
Fri, 5 Apr 2024 10:10:02 +0100 |
On Thu, 04 Apr 2024 20:39:51 -0400
"Dale R. Worley" <worley@alum.mit.edu> wrote:
> "Linde, Evan" <elinde@okstate.edu> writes:
> > In a loop constructed like `... | while read ...`, changes to
> > variables declared outside the loop only have a loop local
> > scope, unlike other "while" or "for" loops.
>
> Yeah, that's a gotcha. But it's a general feature of *pipelines*,
> documented in
>
> Each command in a pipeline is executed as a separate process (i.e., in
> a subshell). See COMMAND EXECUTION ENVIRONMENT for a description of a
> subshell environment. If the lastpipe option is enabled using the
> shopt builtin (see the description of shopt below), the last element of
> a pipeline may be run by the shell process.
>
> To circumvent that, I've sometimes done things like
>
> exec 3<( ... command to generate stuff ... )
> while read VAR <&3; do ... commands to process stuff ... ; done
> exec 3<-
>
> You may be able to condense that to
>
> {
> while read VAR <&3; do ... commands to process stuff ... ; done
> } <( ... command to generate stuff ... )
>
Owing to while being a compound command, it need not be solely enclosed by
another. Optionally, read's -u option may be used to avoid a dup(2) syscall for
each line read. More importantly, the necessary redirection is missing. As
such, your example could be amended as:
while read -r -u3 var; do ... processing commands ...; done 3< <(... generating
commands ...)
In the event that the processing commands are known not to attempt to read from
STDIN, that may be further reduced to:
while read -r var; do ... processing commands ...; done < <(... generating
commands ...)
--
Kerin Millar