在Mac OS上无法将进程替换为“源”

时间:2019-05-09 11:37:34

标签: bash macos

背景

我有一些项目,其中项目版本定义为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)

1 个答案:

答案 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