Can anyone explain this behavior? Running:
#!/bin/sh echo "hello world" | read var1 var2 echo $var1 echo $var2
results in nothing being ouput, while:
#!/bin/sh echo "hello world" > test.file read var1 var2 < test.file echo $var1 echo $var2
produces the expected output:
hello world
Shouldn't the pipe do in one step what the redirection to test.file did in the second example? I tried the same code with both the dash and bash shells and got the same behavior from both of them.
A recent addition to bash
is the lastpipe
option, which allows the last command in a pipeline to run in the current shell, not a subshell, when job control is deactivated.
#!/bin/bash set +m # Deactiveate job control shopt -s lastpipe echo "hello world" | read var1 var2 echo $var1 echo $var2
will indeed output
hello world
#!/bin/sh echo "hello world" | read var1 var2 echo $var1 echo $var2
produces no output because pipelines run each of their components inside a subshell. Subshells inherit copies of the parent shell's variables, rather than sharing them. Try this:
#!/bin/sh foo="contents of shell variable foo" echo $foo ( echo $foo foo="foo contents modified" echo $foo ) echo $foo
The parentheses define a region of code that gets run in a subshell, and $foo retains its original value after being modified inside them.
Now try this:
#!/bin/sh foo="contents of shell variable foo" echo $foo { echo $foo foo="foo contents modified" echo $foo } echo $foo
The braces are purely for grouping, no subshell is created, and the $foo modified inside the braces is the same $foo modified outside them.
Now try this:
#!/bin/sh echo "hello world" | { read var1 var2 echo $var1 echo $var2 } echo $var1 echo $var2
Inside the braces, the read builtin creates $var1 and $var2 properly and you can see that they get echoed. Outside the braces, they don't exist any more. All the code within the braces has been run in a subshell because it's one component of a pipeline.
You can put arbitrary amounts of code between braces, so you can use this piping-into-a-block construction whenever you need to run a block of shell script that parses the output of something else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With