Found my answer, sort of. Either use mkfiko and tee, or use bash/zsh/ksh88 process substitution a la "cmd >(subcmd1) >(subcmd2)", 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.
T=$(openssl x509 -noout -text -in "$1") EXPD=$(date -d"$(echo "$T" | sed -n 's/^.*Not After : //p')" +%Y%b%d) SUBJ=$(echo "$T" | sed -n 's/^.*Subject: .*CN = //p')
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>
Talk about unreadable, though!
This does several things, as I understand it: 1. duplicate /dev/fd/1 (stdout) to, usually, /dev/fd/4 but it doesn't really matter which FD# 2. spawns the first subshell, and passes /dev/fd/1 as that subshell's stdin, and the subshell's stdout as the parent process's stdout 3. spawns the second subshell, and passes the dup'd FD (/dev/fd/4 or whatever it is) as that subshell's stdin, and the subshell's stdout as the parent process's stdout 4. collects all the output
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...
-Adam
-----Original Message----- From: Trevor Cordes trevor@tecnopolis.ca Sent: Sunday, February 26, 2023 8:23 PM To: Adam Thompson athompso@athompso.net Cc: Continuation of Round Table discussion roundtable@muug.ca Subject: Re: [RndTbl] shell quoting inside $( )?
I can't see any way to "bifurcate output" in bash without using tee. I'm pretty sure zsh (and probably fish) can do it, but not sure of the syntax there either:
$ eval $((openssl x509 -noout -text -in /etc/pki/tls/certs/tecnopolis.ca.crt | tee >(echo -n EXPD="'"`date -d"$(sed -n 's/^.*Not After : //p')" +%Y%b%d`"'" ) >(echo SUBJ="'"`sed -n 's/^.*Subject: .*CN = //p'`"'" ) 1>&2 ) 2>/dev/null)
$ echo $SUBJ tecnopolis.ca $ echo $EXPD 2024Feb22
If you can figure out a way to get the vars out of the subshell and into 2 different vars without using the eval $() then you're probably better off. Even though I protect the tainted inputs with '', someone could possibly plant a ' in the SUBJ and thus this is a sec hole.
Of course you could eliminate the eval and assign to a var and then run a 2nd command to split them into SUBJ and EXPD, but I was going for a oneliner. (Get rid of the "'" adders then.)
I'm going to toy with the idea of using {} subshells which might allow elimination of the eval.
Of course this would be much cleaner in a perl oneliner... and if you're already bringing in sed, how much worse is perl?