简体   繁体   English

Dash 和 C: eval "$(

[英]Dash and C: eval "$(<cmdfile)" and system("eval \"\$(<cmdfile)\"") giving different results

I would like to use the system() function in C to evaluate an expression within a file cmdfile but I'm not getting the same results as when I do so on the command line directly.我想在 C 中使用system()函数来计算文件cmdfile 中的表达式,但我没有得到与直接在命令行上执行此操作时相同的结果。 The content of cmdfile is the following: cmdfile的内容如下:

$ cat cmdfile
echo hello

and when I evaluate its content on the command line directly, it works:当我直接在命令行上评估其内容时,它可以工作:

$ eval "$(<cmdfile)"
hello

To do the same in C, I'm using system().为了在 C 中做同样的事情,我使用 system()。 This is my code:这是我的代码:

$ 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;
}

The trouble is that I don't see any output when using the above code:问题是我在使用上面的代码时没有看到任何输出:

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

There should be hello printed right after the printf output but it doesn't work.在 printf 输出之后应该立即打印hello但它不起作用。 Still, I know that system() is definitely doing something, because if I give it a non-existing filename, dash complains:尽管如此,我知道 system() 肯定在做某事,因为如果我给它一个不存在的文件名,dash 会抱怨:

$ ./systest "eval \"\$(<cmdfileFF)\""
eval "$(<cmdfileFF)"
sh: 1: cannot open cmdfileFF: No such file

and if I just evaluate echo hello without involving cmdfile , it works too:如果我只是在不涉及cmdfile 的情况下评估echo hello ,它也可以工作:

$ ./systest "eval \"echo hello\""
eval "echo hello"
hello

I'd like to know what is causing this difference in behaviour.我想知道是什么导致了这种行为差异。 Is there any other way of executing the content of cmdfile in dash?有没有其他方法可以在 dash 中执行cmdfile的内容? I'm restricted to only using the built-in commands of dash on the command line, so options such as ./systest "eval \\"\\$(cat cmdfile)\\"" are not possible.我仅限于在命令行上使用 dash 的内置命令,因此诸如./systest "eval \\"\\$(cat cmdfile)\\""是不可能的。 Further, the expansion of "$(<cmdfile)" should only happen within system(), not before (thus ./systest "eval \\"$(<cmdfile)\\"" won't work.此外, "$(<cmdfile)"的扩展应该只发生在 system() 中,而不是之前(因此./systest "eval \\"$(<cmdfile)\\""将不起作用。

I tested this with dash 0.5.10.2-6 and dash 0.5.8-2.1ubuntu2.我用破折号 0.5.10.2-6 和破折号 0.5.8-2.1ubuntu2 对此进行了测试。

Thank you for any insight!感谢您的任何见解!

Edit编辑

Thanks to Jonathan Leffler's comment, I now realise that dash doesn't understand the $(<file) syntax.感谢 Jonathan Leffler 的评论,我现在意识到破折号不理解$(<file)语法。 So what would be a dash-compatible equivalent?那么什么是破折号兼容的等价物呢?

Wrap-up包起来

So my confusion was due to the fact that system(...) always uses /bin/sh, but when testing my expressions on the command line, I was accidentally invoking bash instead of dash.所以我的困惑是由于 system(...) 总是使用 /bin/sh,但是在命令行上测试我的表达式时,我不小心调用了 bash 而不是 dash。 Hence the results were different.因此结果是不同的。

$(< …) substitution isn't POSIX-sh-compatible, but your sh is restricted to about that. $(< …)替换与 POSIX-sh 不兼容,但您的 sh 仅限于此。 A general alternative is to replace < cmdfile with cat cmdfile :一般的替代方法是将< cmdfile替换为cat cmdfile

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

but I think dot-sourcing is equivalent in this case:但我认为dot-sourcing在这种情况下是等效的:

./systest '. ./cmdfile'

The proper fix is to put a shebang line in the script and mark it as executable.正确的解决方法是在脚本中放置一个shebang 行并将其标记为可执行文件。

#!/bin/sh
echo "hello"

The shebang needs to be the absolutely first line of the file (its first two bytes should be # and ! ). shebang 必须是文件的绝对第一行(它的前两个字节应该是#! )。 The quoting around the argument to echo is not strictly necessary here, but good practice.在这里引用echo的参数并不是绝对必要的,而是一种很好的做法。 (See also When to wrap quotes around a shell variable? ) (另请参阅何时在 shell 变量周围加上引号?

Changing the permissions only needs to be done once, when you have just created the file:当您刚刚创建文件时,更改权限只需执行一次:

chmod +x ./cmdfile

Now, you can simply use现在,您可以简单地使用

system("./cmdfile")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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