Mac OS下source结合进程替换失效的原因及解决方法
macOS Mojave中bash进程替换失效的原因及无临时文件解决方案
为啥source <(parseNow)和管道方式都不管用?
你碰到的问题其实和macOS预装的老旧bash版本直接相关,主要有两个核心原因:
bash 3.2不支持进程替换:macOS Mojave自带的bash是3.2.57版本——这是Apple因为GPL许可证限制一直停更的旧分支,和现在主流的bash 5.x差了好几个世代。虽然理论上bash 3.2支持进程替换(
<()语法),但Apple在编译这个版本时禁用了该特性,所以你在Mojave里用<()根本不会生效。管道运行在子shell里:你试的
parseNow | source /dev/fd/0之所以没效果,是因为管道里的每个命令都在独立的子shell中执行。source在这里是在子shell里处理输入,它设置的版本变量只会留在子shell里,子shell一退出,这些变量就没了,父shell根本拿不到。
不用临时文件的解决办法
最靠谱的替代方案是用eval命令,直接在当前shell环境里执行parseNow的输出:
eval "$(parseNow)"
原理很简单:
$(parseNow)会把你的脚本输出(比如VERSION_MAJOR=3; VERSION_MINOR=1这类赋值语句)捕获成字符串eval会在当前shell里直接执行这些赋值,变量会直接保存在当前环境中,效果和source临时文件完全一样。
举个实际例子,如果你的parseNow脚本输出是:
VERSION_MAJOR=2 VERSION_MINOR=4 VERSION_PATCH=1
执行eval "$(parseNow)"之后,直接在shell里敲echo $VERSION_PATCH就能得到1,完全不需要临时文件绕一圈。
额外小提示
如果你的项目经常需要用到bash的高级特性,建议通过Homebrew安装新版bash(比如bash 5.x),然后把默认shell切换过去。新版bash支持进程替换、关联数组等实用功能,能避开很多旧版本的兼容性坑。
内容的提问来源于stack exchange,提问作者Marek R
相关产品推荐
相关产品推荐

