This page is for Bash programming tips and tricks, most of which will only be code fragments.
Completed solutions should probably go in Useful One-Liners.
Keeping while in context
From Bob Dunlop
I’ve long been annoyed by the behaviour of Bash and pipelines as exhibited by the following small script.
#!/bin/bash generate() { echo "one" echo "two" echo "three" } last="dummy" generate | while read x do last=$x echo "x= $x last= $last" done echo "last= $last"
Which produces the following output.
x= one last= one x= two last= two x= three last= three last= dummy
Notice that despite “last” being updated within the while loop this change is not reflected in the main body of the code. The reason being that the while statement as part of a pipeline is being run in a separate subshell.
Since I frequently need to process generated output and set flags accordingly I find this behavior rather inconvenient.
The following is a recoding of the while loop which avoids the pipeline (replacing it with a named pipe) that allows the while to be run by the current shell.
while read x do last=$x echo "x= $x last= $last" done < <( generate )
Which produces the better (for me at least) output:
x= one last= one x= two last= two x= three last= three last= three
Warning the <( command )
construct is specific to bash, and ZSH. The space between the two <
in the example is also important and required.
Leave a Reply
You must be logged in to post a comment.