[RndTbl] shell quoting inside $( )?

Trevor Cordes trevor at tecnopolis.ca
Sun Feb 26 21:56:54 CST 2023


On 2023-02-27 Adam Thompson wrote:
> Found my answer, sort of.  Either use mkfiko and tee, or use
> bash/zsh/ksh88 process substitution a la "cmd >(subcmd1) >(subcmd2)",

That's what I said half an hour ago!  Doh

I managed to improve mine to eliminate the eval:

$ read SUBJ EXPD <<<$(echo $((openssl x509 -noout -text -in /etc/pki/tls/certs/tecnopolis.ca.crt |tee >(date -d"$(sed -n 's/^.*Not After : //p')" +%Y%b%d)  >(sed -n 's/^.*Subject: .*CN = //p') 1>&2 ) 2>/dev/null))

$ echo "subj $SUBJ  expd $EXPD"
subj tecnopolis.ca  expd 2024Feb22

> but I don't see any good way of getting the output from subcmd1/2
> into variables as they run in subshells.  It would be do-able by
> piping the whole thing into a "while read X" loop, but that's
> arguably getting into "the cure is worse than the disease" territory.

Yes, the subshell/command problem is the difficult factor here.  My
updated example above also uses read, but without a loop.  You need
the echo and multi-subshells to get the 2 outputs onto 1 line.

Here's the funny part: the >() constructs start async ps's and you
don't know whose output will come first!  Yet no matter what I did
the SUBJ always comes out first.  I even put sleeps in the >()
constructs to try to influence who outputs first, but it didn't
matter!  I wonder why the output order is the way it is (backwards)
and always constant...

> Untested as yet, but should work:
> 
> ( openssl x509 -noout -text -in "$1" >(sed -n 's/^.*Not After : /A
> /p' | xargs date +%Y%b%d -d) >(sed -n 's/^.*Subject: .*CN = /B /p') )
> | while read X; do case $X in A) EXPD="$X" ;; B) SUBJ="$X" ;; esac ;
> <do something with EXPD and SUBJ>

Pretty sure you are *forced* to use tee or something like it.  You
can't just use >() with openssl.  >() replaces itself with
/dev/fd/X and sets up an async to read from it, which means nothing
to openssl.  You need tee to do the writing to that fd/X.  Ran into
that grief when I was working on it.

Nice: you are getting around the order issue with A / B, which is
smart, but then kind of forces you into the loop.  Still one line
though.  And the loop is no more evil than my read <<< echo hack.

> If there were an easy way to "promote" shell variables up out of
> their subshell namespaces without needing `` or $() or read,
> subshells would be a heck of a lot more useful...

I was trying really hard to use my own fd's like 3 & 4 (not the
ones used by >()) to get the output out of each >() construct
and be able to differentiate them.  But it wouldn't work... maybe
because the >() is async, and I need to write to each fd in the
construct and then read them out of the construct.  Dunno.  Use
of fds 3 & 4 hurts my brain.  Ideally the EXPD >() could write out
to fd3 and SUBJ to fd4 and an outer shell could then read them.
Or maybe that's impossible.


More information about the Roundtable mailing list