HPR2793: bash coproc: the future (2009) is here


Manage episode 231482971 series 108988
Discovered by Player FM and our community — copyright is owned by the publisher, not Player FM, and audio streamed directly from their servers.

If you want the full manuscript, that’s at gitlab: hpr2793_bash_coproc_manuscript.adoc. It’s almost a transcript, but I added spontaneous commentary while reading the examples, so that’s not in the manuscript.

Episode errata:

  • Command substitution with $() is perfectly valid according to POSIX, and is accepted both by dash and by bash --posix. It’s not to be considered a bashism.

  • I fumbled the pronunciation of the printf format string in one place and said "parenthesis" instead of "percentage sign".

  • I tried to say "space" every time there’s a space, but I know I forgot it in a few places. But you probably need to look at the show notes to really make sense of the commands anyway.

Example #1:

More on command substitution in Dave’s hpr1903: Some further Bash tips.

Example #2:

You can also combine process substitution with redirection.

Example #3:

More on process substitution in Dave’s hpr2045: Some other Bash tips.

For a description of a hack for creating bidirectional anonymous pipes in bash, see my Fediverse post on this, and I owe you a show.

A coprocess in bash is a subshell to which you have access to two file descriptors: Its stdin and its stdout.

The two file descriptors will be put in a bash array. To learn more about arrays, check out Dave’s series within the bash series, a whopping five-part quadrology including hpr2709, hpr2719, hpr2729, hpr2739 and hpr2756.

You create a coprocess using the coproc keyword, brand spanking new since bash 4 from 2009. I am filing issues to pygments and GNU src-highlite to support it.

There are two ways to call coproc. The first way is to give coproc a simple command.

Example #4:

The other way is to give coproc an explicit name and a Command Grouping.

Example #5:

Slightly less contrived example #6:

$ coproc GREP (grep --line-buffered pub); printf '%s\n' hacker public radio >&${GREP[1]}; cat <&${GREP[0]} [1] 25627 public ^C $ kill %1 [1]+ Terminated coproc GREP ( grep --color=auto --line-buffered pub )

Here grep and cat wait forever for more input, so we have to kill them to continue our lesson.

But we know that GREP will only return one line, so we can just read that one line. And when we are done feeding it lines, we can close our side of its stdin, and it will notice this and exit gracefully.

I’m glad I stumbled over that {YOURVARIABLE}>&- syntax for having a dereferenced variable as the left FD of a redirection. Originally I used an ugly eval.

Example #7:

$ coproc GREP (grep --line-buffered pub); printf '%s\n' hacker public radio >&${GREP[1]}; head -n1 <&${GREP[0]}; exec {GREP[1]}>&- [1] 25706 public [1]+ Done coproc GREP ( grep --color=auto --line-buffered pub )

There we go! Not the most brilliant example, but it shows all the relevant moving parts, and we covered a couple of caveats.

Now go out and play with this and come back with an example on how this is actually useful in the real world, and submit a show!

2835 episodes available. A new episode about every day .