1

Context: I have a script which makes multiple calls to bc to set some values, ie: many foo="$(echo '1/3' | /usr/bin/bc -q)"

What I want to achieve: do not call bc every times, but keep one bc instance and re-use it multiple times.

I guess coproc may be what I need, but as I’m curious and want to understand how Bash works, I try to do it using named pipes.

This is my code so far, not the code of the script on which I intend to do this, but a code sample I wrote to try to help me understand what’s going on. It’s probably full of UUO* and questionable parts, but you’ll tell me then:

#!/bin/env -S -i bash --norc

set -euo pipefail
IFS=$'\t\n'

init_bc() {
    [[ -p /tmp/bci    ]] || mkfifo /tmp/bci
    [[ -p /tmp/bco    ]] || mkfifo /tmp/bco
    tail -n1 -f    >&/tmp/bci            &
    cat              /tmp/bco            &
    /usr/bin/bc -q   /tmp/bci >&/tmp/bco &
    echo "scale=50" >/tmp/bci
    wait &
}

do_bc() {
    echo "${1}" >/tmp/bci >&1
}

do_exit() {
    rm -vf /tmp/{bci,bco} >&2
    pkill -e -P $$
}

trap do_exit TERM EXIT INT
init_bc
echo Sleeping… >&2
foo="$(do_bc "${1}")"
echo "FOO: ${foo}"
sleep 5
echo "Awake!" >&2
wait &
echo "End of script. We wait for all sub-shells." >&2
wait

Running it (waiting a few seconds and then hitting Ctrl+C) this is what I get:

$ ./piped_bc '1/7'
Sleeping…
FOO: 
.14285714285714285714285714285714285714285714285714
Awake!
End of script. We wait for all sub-shells.
^Cremoved '/tmp/bci'
removed '/tmp/bco'
 killed (pid 5585)
 killed (pid 5586)
 killed (pid 5587)

As you can see, the $foo variable doesn’t get valued, and this is what I do not understand.

The bc result seems to be “going” to the standard output, because if I run the script adding 1>/dev/null the result isn’t displayed, but I don’t understand why $foo is not valued then, and it upsets me (more than I’d like to admit).

Last thing which may be of interest for my question: If I do this in the terminal:

foo=$(/usr/bin/bc -q <(echo 'scale=7;1/7') &)

The variable $foo gets the result of 1/7 as expected:

$ echo $foo
.1428571

Why is it not in my script?

Any help would be, of course, greatly appreciated.

5

0

Browse other questions tagged or ask your own question.