我有一些项目,其中项目版本定义为C头文件中的宏。 我找到了一种从C头文件中获取数据并在Mac OS上的某些bash脚本中进行处理的方法。
由于某种原因,当我将数据提供给source
命令时,“进程替换”不起作用。
这是测试bash脚本:
#!/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
这将产生以下输出:
.. 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
您可以看到source parseNow
部分无效,但是copy parseNow
确实有效,即使复制是通过将进程替换为临时文件来执行的。
这是示例标头:
#define BUILD_NUMBER 1047
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_MILESTONE "v1.3"
// other stuff
为什么source <(parseNow)
不起作用(在Mac OS Mojave上)?
我可以解决吗?
我希望我不必使用临时文件来处理此C头文件。这是不得已的方法。
echo $BASH_VERSION
打印3.2.57(1)-release
根据评论,其他无效的步骤:
parseNow | source /dev/fd/0
source /dev/fd/0 < <(parseNow)
parseNow | source - # line 26: -: No such file or directory
source - < <(parseNow)
答案 0 :(得分:3)
如this answer中所述,source
在较旧的bash版本中不能用于进程替换。
但是,由于相同答案中提出的解决方法似乎并不适合您,因此让我提出一个替代方案:
eval "$(parseNow)"
我知道,eval
很不好,但是source /dev/stdin <<< "string"
和eval "string"
之间确实没有区别。
我个人认为,嘘eval
并不是所有其他不安全的构造都是双重标准。 shellcheck
的作者针对此问题撰写了一篇非常有趣的博客文章:
white collar eval: [[ $var -eq 42 ]]
runs arbitrary code too