<p>If you want the full manuscript, that’s at <a href="https://gitlab.com/clacke/hpr/blob/master/hpr2793_bash_coproc_manuscript.adoc">gitlab: hpr2793_bash_coproc_manuscript.adoc</a>. It’s almost a transcript, but I added spontaneous commentary while reading the examples, so that’s not in the manuscript.</p>
<p>Episode errata:</p>
<ul>
<li><p>Command substitution with <code>$()</code> is perfectly valid according to POSIX, and is accepted both by <code>dash</code> and by <code>bash --posix</code>. It’s not to be considered a bashism.</p></li>
<li><p>I fumbled the pronunciation of the <code>printf</code> format string in one place and said &quot;parenthesis&quot; instead of &quot;percentage sign&quot;.</p></li>
<li><p>I tried to say &quot;space&quot; 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.</p></li>
</ul>
<p>Example #1:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb1-1" data-line-number="1">$ <span class="bu">echo</span> <span class="va">$(</span><span class="bu">echo</span> hacker public radio<span class="va">)</span></a>
<a class="sourceLine" id="cb1-2" data-line-number="2"><span class="ex">hacker</span> public radio</a>
<a class="sourceLine" id="cb1-3" data-line-number="3">$ <span class="va">$(</span><span class="bu">echo</span> echo hacker public radio<span class="va">)</span>  # <span class="ex">It</span> can even supply the command itself, not just parameters. Note the word splitting.</a>
<a class="sourceLine" id="cb1-4" data-line-number="4"><span class="ex">hacker</span> public radio</a>
<a class="sourceLine" id="cb1-5" data-line-number="5">$ <span class="st">&quot;</span><span class="va">$(</span><span class="bu">echo</span> echo hacker public radio<span class="va">)</span><span class="st">&quot;</span>  # <span class="ex">Counteract</span> word splitting by putting the command substitution in quotes.</a>
<a class="sourceLine" id="cb1-6" data-line-number="6"><span class="ex">bash</span>: echo hacker public radio: command not found</a>
<a class="sourceLine" id="cb1-7" data-line-number="7">$ <span class="kw">`</span><span class="bu">echo</span> echo hacker public radio<span class="kw">`</span>  # <span class="ex">Old-style</span> command substitution</a>
<a class="sourceLine" id="cb1-8" data-line-number="8"><span class="ex">hacker</span> public radio</a></code></pre></div>
<p>More on command substitution in Dave’s <a href="https://hackerpublicradio.org/eps.php?id=1903">hpr1903: Some further Bash tips</a>.</p>
<p>Example #2:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb2-1" data-line-number="1">$ <span class="bu">echo</span> <span class="op">&lt;(</span><span class="bu">echo</span> hacker public radio<span class="op">)</span></a>
<a class="sourceLine" id="cb2-2" data-line-number="2"><span class="ex">/dev/fd/63</span></a>
<a class="sourceLine" id="cb2-3" data-line-number="3">$ <span class="fu">cat</span> <span class="op">&lt;(</span><span class="bu">echo</span> hacker public radio<span class="op">)</span></a>
<a class="sourceLine" id="cb2-4" data-line-number="4"><span class="ex">hacker</span> public radio</a></code></pre></div>
<p>You can also combine process substitution with redirection.</p>
<p>Example #3:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb3-1" data-line-number="1">$ <span class="bu">echo</span> hacker public radio <span class="op">&gt;</span> <span class="op">&gt;(</span><span class="fu">sed</span> -e <span class="st">&#39;s/$/!/&#39;</span><span class="op">)</span>  # You need the space between the greater-thans here!</a>
<a class="sourceLine" id="cb3-2" data-line-number="2"><span class="ex">hacker</span> public radio!</a></code></pre></div>
<p>More on process substitution in Dave’s <a href="https://hackerpublicradio.org/eps.php?id=2045">hpr2045: Some other Bash tips</a>.</p>
<p>For a description of a hack for creating bidirectional anonymous pipes in bash, see <a href="https://libranet.de/display/0b6b25a8-135c-83e5-1f4b-82a136800329">my Fediverse post on this</a>, and I owe you a show.</p>
<p>A coprocess in bash is a subshell to which you have access to two file descriptors: Its stdin and its stdout.</p>
<p>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 <a href="https://hackerpublicradio.org/eps.php?id=2709">hpr2709</a>, <a href="https://hackerpublicradio.org/eps.php?id=2719">hpr2719</a>, <a href="https://hackerpublicradio.org/eps.php?id=2729">hpr2729</a>, <a href="https://hackerpublicradio.org/eps.php?id=2739">hpr2739</a> and <a href="https://hackerpublicradio.org/eps.php?id=2756">hpr2756</a>.</p>
<p>You create a coprocess using the <code>coproc</code> keyword, brand spanking new since bash 4 from 2009. I am filing issues to <a href="https://bitbucket.org/birkenfeld/pygments-main/issues">pygments</a> and <a href="https://savannah.gnu.org/bugs/?group=src-highlite">GNU src-highlite</a> to support it.</p>
<p>There are two ways to call coproc. The first way is to give <code>coproc</code> a <em>simple command</em>.</p>
<p>Example #4:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb4-1" data-line-number="1">$ <span class="ex">coproc</span> :<span class="kw">;</span> <span class="bu">declare</span> -p <span class="va">COPROC</span></a>
<a class="sourceLine" id="cb4-2" data-line-number="2">[<span class="ex">1</span>] 25155</a>
<a class="sourceLine" id="cb4-3" data-line-number="3"><span class="bu">declare</span> -a <span class="va">COPROC=([0]=</span><span class="st">&quot;63&quot;</span> <span class="va">[1]=</span><span class="st">&quot;60&quot;</span><span class="va">)</span></a>
<a class="sourceLine" id="cb4-4" data-line-number="4">[<span class="ex">1</span>]+  Done                    coproc COPROC :</a></code></pre></div>
<p>The other way is to give <code>coproc</code> an explicit name and a <a href="https://www.gnu.org/software/bash/manual/bash.html#Command-Grouping">Command Grouping</a>.</p>
<p>Example #5:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb5-1" data-line-number="1">$ <span class="ex">coproc</span> HPR (:); <span class="bu">declare</span> -p <span class="va">HPR</span></a>
<a class="sourceLine" id="cb5-2" data-line-number="2">[<span class="ex">1</span>] 25469</a>
<a class="sourceLine" id="cb5-3" data-line-number="3"><span class="bu">declare</span> -a <span class="va">HPR=([0]=</span><span class="st">&quot;63&quot;</span> <span class="va">[1]=</span><span class="st">&quot;60&quot;</span><span class="va">)</span></a>
<a class="sourceLine" id="cb5-4" data-line-number="4">[<span class="ex">1</span>]+  Done                    coproc HPR ( : )</a></code></pre></div>
<p>Slightly less contrived example #6:</p>
<pre><code>$ coproc GREP (grep --line-buffered pub); printf &#39;%s\n&#39; hacker public radio &gt;&amp;${GREP[1]}; cat &lt;&amp;${GREP[0]}
[1] 25627
public
^C
$ kill %1
[1]+  Terminated              coproc GREP ( grep --color=auto --line-buffered pub )</code></pre>
<p>Here grep and cat wait forever for more input, so we have to kill them to continue our lesson.</p>
<p>But we know that <code>GREP</code> 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.</p>
<p>I’m glad I stumbled over that <code>{YOURVARIABLE}&gt;&amp;-</code> syntax for having a dereferenced variable as the left FD of a redirection. Originally I used an ugly <code>eval</code>.</p>
<p>Example #7:</p>
<pre><code>$ coproc GREP (grep --line-buffered pub); printf &#39;%s\n&#39; hacker public radio &gt;&amp;${GREP[1]}; head -n1 &lt;&amp;${GREP[0]}; exec {GREP[1]}&gt;&amp;-
[1] 25706
public
[1]+  Done                    coproc GREP ( grep --color=auto --line-buffered pub )</code></pre>
<p>There we go! Not the most brilliant example, but it shows all the relevant moving parts, and we covered a couple of caveats.</p>
<p>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!</p>

