Reputation: 37657
I have some project where project version is defined as macros in C header file. I've found the way to fetch this data from a C header file and process that in some bash script on Mac OS.
For some reason "Process substitution" doesn't work when I feed this data to a source
command.
Here is test bash script:
#!/bin/bash
VERSION_BUILD_FILE=$(dirname $0)/Somepath/Version.h
function parseNow() {
gcc -E -dM "$VERSION_BUILD_FILE" | sed -E '{
/^#define (VERSION_M|BUILD_NUMBER)/!d
/#define[ \t]*[^ \t]*$/d
s/[^ \t]*[ \t]*([^ \t]*)[ \t]*(.*)/\1=\2/
/(""|\([^\)]*\))/d
}'
}
function checkVersioVer() {
echo "$VERSION_MAJOR.$VERSION_MINOR.$BUILD_NUMBER milestone: $VERSION_MILESTONE"
}
checkVersioVer
echo parseNow result:
parseNow
echo "----"
echo "source parseNow"
source <(parseNow)
checkVersioVer
echo "----"
echo "copy parseNow then source tmp.txt"
cp <(parseNow) tmp.txt
source tmp.txt
rm tmp.txt
checkVersioVer
This produces this output:
.. milestone:
parseNow result:
BUILD_NUMBER=1047
VERSION_MAJOR=1
VERSION_MILESTONE="v1.3"
VERSION_MINOR=3
----
source parseNow
.. milestone:
----
copy parseNow then source tmp.txt
1.3.1047 milestone: v1.3
As you can see source parseNow
part doesn't work but copy parseNow
does work even though copy is performed with process substitution to a temporary file.
Here is a sample header:
#define BUILD_NUMBER 1047
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_MILESTONE "v1.3"
// other stuff
Why source <(parseNow)
doesn't work (on Mac OS Mojave)?
Can I fix it somehow?
I wish I don't have to use temporary file to process this C header file. This is last resort.
echo $BASH_VERSION
prints 3.2.57(1)-release
Based on comments other aproches which do not work:
parseNow | source /dev/fd/0
source /dev/fd/0 < <(parseNow)
parseNow | source - # line 26: -: No such file or directory
source - < <(parseNow)
Upvotes: 2
Views: 1113
Reputation: 27215
As explained in this answer, source
does not work with process substitution in older bash versions.
However, since the workaround presented in the same answer doesn't seem to work for you, let me propose an alternative:
eval "$(parseNow)"
I know, I know, eval
is bad and stuff but there really is no difference between source /dev/stdin <<< "string"
and eval "string"
.
Personally, I think booing eval
but not all the other unsafe constructs is a double standard. There is a highly interesting blog post from the author of shellcheck
on this issue:
white collar eval: [[ $var -eq 42 ]]
runs arbitrary code too
Upvotes: 3