如何在 system() 中使用通配符表达式

How to use a wildcard expression within system()

本文关键字:通配符 表达式 system      更新时间:2023-10-16

以下命令在我的嵌入式Linux(Beaglebone Black)上运行良好:

echo bone_pwm_P9_21 > /sys/devices/bone_capemgr.?/slots

但使用此小C++程序时则不然:

#include <stdlib.h>
#include <string>
int main {
    system(std::string("echo bone_pwm_P9_21 > /sys/devices/bone_capemgr.?/slots").c_str());
    return 0;
}

该问题涉及用作通配符的'?'问号。当传递给 system()std::string中的问号替换为普通字符时,system() 函数将完美计算命令。

我尝试过但没有成功的解决方案:

  • ?替换为?
  • ?替换为*

除了你的代码不可编译之外,这还会失败,因为system(3)运行sh,通常是dashbusybox提供的最小shell。

同时,您的交互式登录使用bashksh或其他更舒适的shell。

dashbusybox sh 不会对重定向进行全局扩展,而 bashksh 会。以下是您希望获得bash的行为的演示:

$ touch file.txt
$ bash -c 'echo "bash contents" > *.txt'
$ cat file.txt
bash contents

同时,您遇到的问题例如 dash

$ dash -c 'echo "and now dash" > *.txt'
$ ls
*.txt  file.txt
$ cat '*.txt'      # Instead of expanding, the path was taken literally
and now dash
$ cat file.txt
bash contents

要解决此问题,您可以(按首选项顺序)

  1. 用 C 代码而不是 shell 脚本编写 C 程序
  2. execve称呼更好的外壳.
  3. 重写以不写入 glob,例如 echo "stuff" | tee *.txt > /dev/null
  4. system调用更好的外壳,例如 bash -c "echo stuff > *.txt"

注意:正如 πάντα ῥεῖ 指出的那样,system()命令调用 shell,当出现正确的通配符时,它通常会进行扩展:* 。如果您希望控件单独调用每个system(),或者基础 shell 受到限制,则此答案更合适。

原答案:

也许你可以在进行system()调用之前使用 wordexp 来构造你的字符串:

#include <string>
#include <vector>
#include <iostream>
#include <wordexp.h>
std::vector<std::string> expand_env(const std::string& var, int flags = 0)
{
    std::vector<std::string> vars;
    wordexp_t p;
    if(!wordexp(var.c_str(), &p, flags))
    {
        if(p.we_wordc)
            for(char** exp = p.we_wordv; *exp; ++exp)
                vars.push_back(exp[0]);
        wordfree(&p);
    }
    return vars;
}
int main()
{
    for(auto&& s: expand_env("$HOME/*")) // <= Note the wildcard '*'
        std::cout << s << 'n';
}

在您的特定情况下,您可以使用这样的东西:

int main()
{
    std::vector<std::string> devices = expand_env("/sys/devices/bone_capemgr.*/slots");
    for(std::vector<std::string>::size_type i = 0; i < devices.size(); ++i)
        system(("echo bone_pwm_P9_21 > " + devices[i]).c_str());
}