【问题标题】:Can't understand why this causes an error不明白为什么这会导致错误
【发布时间】:2023-04-10 01:50:01
【问题描述】:

我有一个很大的音乐目录,列在一个名为op 的文件中。我已经能够构建一个命令,该命令将使用一些创造性的数学从 op 文件中随机选择一首歌曲,并使用 date 命令的纳秒输出。从命令行可以正常工作:

sed -n $((10#$(date +%N)%$(wc -l /shared/southpark/music/op|cut -d ' ' -f 1)))p /shared/southpark/music/op

我想在一个 c 程序中包含这个命令,并用 popen 读取该行。

#include <stdio.h>
#include <string.h>

int main (int argc, char *argv[])
{
        char command[201];
        char buf[501];
        FILE *fp;

        strcpy(command, "sed -n $((10#$(date +%N)%$(wc -l /shared/southpark/music/op|cut -d ' ' -f 1)))p /shared/southpark/music/op");

        if((fp = popen(command, "r")) == NULL)
        {
                fprintf(stderr, "music_player: popen failed\n");
                return(1);
        }

        if(fgets(buf, sizeof(buf), fp) == NULL)
        {
                fprintf(stderr, "music_player: fgets failed\n");
                return(1);
        }

        printf("%s\n", buf);
        pclose(fp);
        return(0);
}

但是当我运行它时,我得到以下错误:

sh: 1: arithmetic expression: expecting EOF: "10#271445839%2278"
music_player: fgets failed

我该怎么做?我不理解错误消息。

【问题讨论】:

  • 认为这可能是重复的stackoverflow.com/questions/15882799/…
  • 您知道$RANDOM 变量或sort -R 命令吗?
  • 等等,如果你在写 C,为什么还要调用 shell?
  • @o11c - 为什么他不应该从 C 程序调用 shell?
  • @Cyclone 因为大多数 shell 功能都是用 C 轻松实现的,没有子进程的开销。

标签: c linux popen fgets


【解决方案1】:

在尝试使用 nneonneo 的两个选项都失败后,我不得不求助于将命令放在 bash 脚本文件中,然后我打开了脚本。它给了我想要的结果。

#include <stdio.h>
#include <string.h>

int main (int argc, char *argv[])
{
        char command[201];
        char buf[501];
        FILE *fp;

        strcpy(command, "/dea/testing/popen/get_file");

        if((fp = popen(command, "r")) == NULL)
        {
                fprintf(stderr, "music_player: popen failed\n");
                return(1);
        }

        if(fgets(buf, sizeof(buf), fp) == NULL)
        {
                fprintf(stderr, "music_player: fgets failed\n");
                return(1);
        }

        printf("%s", buf);
        pclose(fp);
        return(0);
}

【讨论】:

    【解决方案2】:

    popen 执行你的命令使用

    /bin/sh -c "command"
    

    而您的 sh 不理解 10# 基本转换前缀。您之前一直在 bash 中运行该命令。

    要修复,您有两种选择:

    1. 丢弃不必要的10# 前缀(它是默认值)以实现sh 兼容性
    2. 使用bash

      popen("bash -c 'command'", ...)
      

    【讨论】:

    • 我必须使用十进制转换,因为 date 的纳秒选项将包含前导零,这会与早期的尝试混淆。
    • 并将命令更改为strcpy(command, "bash -c \"sed -n $((10#$(date +%N)%$(wc -l /shared/southpark/music/op|cut -d ' ' -f 1)))p /shared/southpark/music/op\""); 会产生与上述相同的错误。
    • 不要使用date +%N,而是考虑使用(${RANDOM}&lt;&lt;15) + ${RANDOM},它使用bash的内置随机数生成器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多