[Techtalk] weirdness piping to a variable
Chris Wilson
chris+linuxchix at aptivate.org
Wed Sep 11 12:43:23 UTC 2013
Hi Miriam,
On Wed, 11 Sep 2013, Miriam English wrote:
> echo "quick brown fox" | cut -d' ' -f2 | ( read a ; echo $a )
>
> It works, but it appears that I can only use "read" inside the parenthesised
> part. I have no idea why. If I try to do it without the parentheses like
> this:
>
> echo "quick brown fox" | cut -d' ' -f2 | read a ; echo $a
>
> nothing happens. I don't understand why.
>
> As I understand it, the part inside parentheses is another process. I can get
> variables into it, but unfortunately not out.
>
> a="one" ; echo "two" | (read b ; echo "$a and $b") ; echo "$a and $b."
Any command that contains a semicolon is two separate commands, split
around the semicolon, and executed one after the other. You probably
already know that, but bear it in mind.
Any command that contains a pipe, splits into multiple separate processes,
one for each stage of the pipe. The first part executes in the parent
process. So taking your example:
echo "quick brown fox" | cut -d' ' -f2 | read a ; echo $a
The first process executes 'echo "quick brown fox"; echo $a', and then
prompts you for another command.
The second process executes "cut -d' ' -f2", and terminates when it
finishes.
The third process executes "read a", and terminates when it finishes.
Processes don't share variables, so the results of "read a" are locked in
process 3's memory, and die with it. However, they do *inherit* variables,
so process 3 starts with a copy of any variables set in process 1, but
can't modify them.
> It's nice to be able to pipe values into a variable because it maintains
> the left to right conceptual flow and makes it easier for me to
> understand what I was doing when I come back much later, but it isn't
> much help if I can't use the variables outside the parentheses.
Yes it is nice, but it's not how pipes work. You either need to rearrange
your pipes so that the set variables stay at the beginning, for example:
read a < <(echo "quick brown fox" | cut -d' ' -f2); echo $a
Or do more work in the subshell (third process), as you did with
parentheses (a while loop works too), or write the results to a file and
read them back:
echo "quick brown fox" | cut -d' ' -f2 > /tmp/tempfile
read a < /tmp/tempfile
Cheers, Chris.
--
Aptivate | http://www.aptivate.org | Phone: +44 1223 967 838
Citylife House, Sturton Street, Cambridge, CB1 2QF, UK
Aptivate is a not-for-profit company registered in England and Wales
with company number 04980791.
More information about the Techtalk
mailing list