繁体   English   中英

Dash 和 C: eval "$(

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM