[Techtalk] weirdness piping to a variable

Peggy Russell prusselltechgroup at gmail.com
Fri Oct 18 01:46:19 UTC 2013


>> some_var=$(command | command | command)

> It is similar to what I usually do too, though I tend to use backticks.
> (I wonder if there is an advantage to one way rather than the other.)
Hi,

The above command is referred to as "command substitution".
The back-ticks are the old style of quotes.
The $() is a little cleaner to use, especially if you nest commands.
I do what Daneel does, $(), to assign the output of a command to a variable
or array.

https://www.gnu.org/software/bash/manual/bash.html#Command-Substitution
http://wiki.bash-hackers.org/scripting/obsolete
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_03
(I write for bash, but I try to consider portability, thus the IEEE link.)

Process substitution was mention. Some day you might run into this. I did ;-)
If you depend on the sequence of events, proces substitution may not work as
first thought. It is async. Here's a little gotcha.

In the snippet:
+++++++++++++++
declare -A aarr=([would]="1" [wood]="2" [much]="1"
                 [woodchuck]="2" [could]="1" [a]="2"
                 [how]="1" [if]="1" [chuck]="2" )
declare -i total=0
echo "$$ $BASHPID"

for word in "${!aarr[@]}"; do
  if [[ "${total}" -eq 0 ]]; then echo "$$ $BASHPID"; fi
  printf -- '%-10s %d\n' "${word}" "${aarr[$word]}"
  (( total += ${aarr[$word]} ))
#done
done | sort -k2rn
printf -- 'Total %2d\n' "${total}"
+++++++++++++++

The pipe put the for in a subprocess (see $$ $BASHPID). You might try process
substitution:

done > >(sort -k2rn)
# sleep 2s
printf -- 'Total %2d\n' "${total}"

But process substitution is async. The Total may come out before the Details.
You could try a quick fix with sleep. 

Or a function in the background and return the total (echo $total).
Or you could create your own pipe and run the command in the background.
Something like:

mkfifo mypipe
trap 'rm -v mypipe' EXIT
...
printf -- '%-10s %d\n' "${word}" "${aarr[$word]}" > mypipe &
...
sort -k2rn < mypipe

Peggy Russell


More information about the Techtalk mailing list