为什么我的 sha1 不匹配,如果我在 bash 函数中计算它们?
why don't my sha1s match, if I compute them inside a bash function?
(我正在努力为这个问题找到一个好的描述性标题,这将有助于未来的搜索者。欢迎 Suggestions/edits。)
我正在向我的一个 C++ 项目添加一个简单的 TDD 框架(在 bash 中实现)。我的大多数测试都可以简单地 pass/fail 基于 exit() return 值,但有些测试具有复杂的输出,最好通过计算哈希值并与黄金值进行比较来处理。
此外,一些更复杂的测试(从 C++ 编译)被编写为在定义某些环境变量时具有不同的输出行为。因此,我希望黄金值会有所不同,具体取决于那些环境变量。
为了生成我的黄金值,我利用 bash 的 &>
工具来捕获 stdout 和 stderr,以便管道进入 sha1sum
:
echo `RV_TRACE="fib" $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum)`
上述命令的输出以 -
结尾,我的强迫症患者无法忍受。所以我添加了一个对 awk
的调用到 trim 它关闭了:
echo `RV_TRACE="fib" $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum) | awk '{print ;}'`
初步测试表明,上述两种方法都产生了相同的数值结果,符合预期:
038735b655da0162b0d3911ae0ca7bd7230673c1 -
038735b655da0162b0d3911ae0ca7bd7230673c1
到目前为止,还不错。但我实际上希望这个 sha1 生成在 bash 函数中完成,我这样写:
rv_trace_test() {
echo +++ $@ $RV_TESTDIR/$RV_TESTNAME
echo `$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum)`
echo `$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum) | awk '{print ;}'`
}
并这样调用:
rv_trace_test RV_TRACE=\"fib\"
但是现在两个 sha1 计算在数值上不再一致。
+++ RV_TRACE="fib" /home/ryan/src/rv/test/004.001.trace-enabled
b23ce3531305e291ae2d3d2401dbeb93effe9ce6 -
cfd355f46f019acfa451ed1c9044f51d9a589a52
...我一辈子都弄不明白为什么。我试过用 $*
替换 $@
,但似乎没有任何区别。我传入的 envvar 是否有引号,或者我是否转义它们似乎也无关紧要。它甚至不必是我的编译测试甚至知道的 envvar。任何环境变量都会导致函数版本不匹配。
这是什么原因造成的?
展开变量后不处理变量赋值和引号。所以当你这样做时:
echo `$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum)`
它会将 RV_TRACE="fib"
视为要执行的命令,而不是要分配的环境变量。
一个解决方案是在调用函数时设置环境变量,而不是在函数内部设置:
RV_TRACE=fib rv_trace_test
然后从函数中取出$@
。
另一种方法是在函数内部使用 eval
。
rv_trace_test() {
echo +++ $@ $RV_TESTDIR/$RV_TESTNAME
eval "$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum)"
eval "$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum) | awk '{print $1;}'"
}
顺便说一句,
echo `command`
基本上等同于
command
(我正在努力为这个问题找到一个好的描述性标题,这将有助于未来的搜索者。欢迎 Suggestions/edits。)
我正在向我的一个 C++ 项目添加一个简单的 TDD 框架(在 bash 中实现)。我的大多数测试都可以简单地 pass/fail 基于 exit() return 值,但有些测试具有复杂的输出,最好通过计算哈希值并与黄金值进行比较来处理。
此外,一些更复杂的测试(从 C++ 编译)被编写为在定义某些环境变量时具有不同的输出行为。因此,我希望黄金值会有所不同,具体取决于那些环境变量。
为了生成我的黄金值,我利用 bash 的 &>
工具来捕获 stdout 和 stderr,以便管道进入 sha1sum
:
echo `RV_TRACE="fib" $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum)`
上述命令的输出以 -
结尾,我的强迫症患者无法忍受。所以我添加了一个对 awk
的调用到 trim 它关闭了:
echo `RV_TRACE="fib" $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum) | awk '{print ;}'`
初步测试表明,上述两种方法都产生了相同的数值结果,符合预期:
038735b655da0162b0d3911ae0ca7bd7230673c1 -
038735b655da0162b0d3911ae0ca7bd7230673c1
到目前为止,还不错。但我实际上希望这个 sha1 生成在 bash 函数中完成,我这样写:
rv_trace_test() {
echo +++ $@ $RV_TESTDIR/$RV_TESTNAME
echo `$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum)`
echo `$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum) | awk '{print ;}'`
}
并这样调用:
rv_trace_test RV_TRACE=\"fib\"
但是现在两个 sha1 计算在数值上不再一致。
+++ RV_TRACE="fib" /home/ryan/src/rv/test/004.001.trace-enabled
b23ce3531305e291ae2d3d2401dbeb93effe9ce6 -
cfd355f46f019acfa451ed1c9044f51d9a589a52
...我一辈子都弄不明白为什么。我试过用 $*
替换 $@
,但似乎没有任何区别。我传入的 envvar 是否有引号,或者我是否转义它们似乎也无关紧要。它甚至不必是我的编译测试甚至知道的 envvar。任何环境变量都会导致函数版本不匹配。
这是什么原因造成的?
展开变量后不处理变量赋值和引号。所以当你这样做时:
echo `$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum)`
它会将 RV_TRACE="fib"
视为要执行的命令,而不是要分配的环境变量。
一个解决方案是在调用函数时设置环境变量,而不是在函数内部设置:
RV_TRACE=fib rv_trace_test
然后从函数中取出$@
。
另一种方法是在函数内部使用 eval
。
rv_trace_test() {
echo +++ $@ $RV_TESTDIR/$RV_TESTNAME
eval "$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum)"
eval "$@ $RV_TESTDIR/$RV_TESTNAME &> >(sha1sum) | awk '{print $1;}'"
}
顺便说一句,
echo `command`
基本上等同于
command