[英]Dash and C: eval "$(<cmdfile)" and system("eval \"\$(<cmdfile)\"") giving different results
我想在 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但它不起作用。 尽管如此,我知道 system() 肯定在做某事,因为如果我给它一个不存在的文件名,dash 会抱怨:
$ ./systest "eval \"\$(<cmdfileFF)\""
eval "$(<cmdfileFF)"
sh: 1: cannot open cmdfileFF: No such file
如果我只是在不涉及cmdfile 的情况下评估echo hello ,它也可以工作:
$ ./systest "eval \"echo hello\""
eval "echo hello"
hello
我想知道是什么导致了这种行为差异。 有没有其他方法可以在 dash 中执行cmdfile的内容? 我仅限于在命令行上使用 dash 的内置命令,因此诸如./systest "eval \\"\\$(cat cmdfile)\\""
是不可能的。 此外, "$(<cmdfile)"
的扩展应该只发生在 system() 中,而不是之前(因此./systest "eval \\"$(<cmdfile)\\""
将不起作用。
我用破折号 0.5.10.2-6 和破折号 0.5.8-2.1ubuntu2 对此进行了测试。
感谢您的任何见解!
感谢 Jonathan Leffler 的评论,我现在意识到破折号不理解$(<file)
语法。 那么什么是破折号兼容的等价物呢?
所以我的困惑是由于 system(...) 总是使用 /bin/sh,但是在命令行上测试我的表达式时,我不小心调用了 bash 而不是 dash。 因此结果是不同的。
$(< …)
替换与 POSIX-sh 不兼容,但您的 sh 仅限于此。 一般的替代方法是将< cmdfile
替换为cat cmdfile
:
./systest "eval \"\$(cat cmdfile)\""
但我认为dot-sourcing在这种情况下是等效的:
./systest '. ./cmdfile'
正确的解决方法是在脚本中放置一个shebang 行并将其标记为可执行文件。
#!/bin/sh
echo "hello"
shebang 必须是文件的绝对第一行(它的前两个字节应该是#
和!
)。 在这里引用echo
的参数并不是绝对必要的,而是一种很好的做法。 (另请参阅何时在 shell 变量周围加上引号? )
当您刚刚创建文件时,更改权限只需执行一次:
chmod +x ./cmdfile
现在,您可以简单地使用
system("./cmdfile")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.