我想使用C中的system()函数来计算文件cmdfile中的表达式,但得到的结果与直接在命令行上计算时的结果不同。cmdfile的内容如下:

$ cat cmdfile
echo hello

当我直接在命令行上评估它的内容时,它会工作:
$ eval "$(<cmdfile)"
hello

为了在C中执行同样的操作,我使用system()。这是我的代码:
$ cat systest.c
#include <stdio.h>
#include <string.h>

int main (int argc, char* argv[])
{
    char* cmd = argv[1];
    printf("%s\n", cmd);
    system(cmd);
    return 0;
}

问题是,使用上述代码时,我看不到任何输出:
$ ./systest "eval \"\$(<cmdfile)\""
eval "$(<cmdfile)"

在printf输出之后应该有hello print,但是它不起作用。不过,我知道Studio()确实在做一些事情,因为如果我给它一个不存在的文件名,DASH抱怨:
$ ./systest "eval \"\$(<cmdfileFF)\""
eval "$(<cmdfileFF)"
sh: 1: cannot open cmdfileFF: No such file

如果我只计算echo hello而不涉及cmdfile,它也可以工作:
$ ./systest "eval \"echo hello\""
eval "echo hello"
hello

我想知道是什么导致了这种行为上的差异。有没有其他方法可以在dash中执行cmdfile的内容?我只能在命令行上使用dash的内置命令,因此不能使用./systest "eval \"\$(cat cmdfile)\""等选项。此外,"$(<cmdfile)"的扩展应该只发生在system()中,而不是之前(因此,./systest "eval \"$(<cmdfile)\""将不起作用)。
我用dash 0.5.10.2-6和dash 0.5.8-2.1 buntu2对此进行了测试。
谢谢你的洞察力!
编辑
感谢Jonathan Leffler的评论,我现在意识到dash不理解$(<file)语法。那么什么是与短划线兼容的等价物呢?
总结
因此,我的困惑是因为system(…)总是使用/bin/sh,但是在命令行上测试我的表达式时,我意外地调用了bash而不是dash。因此结果是不同的。

最佳答案

$(< …)替换与POSIX sh不兼容,但您的sh仅限于此。一般的替代方法是用< cmdfile替换cat cmdfile

./systest "eval \"\$(cat cmdfile)\""

但我认为dot-sourcing在这种情况下是等价的:
./systest '. ./cmdfile'

10-08 20:08