将标准输出捕获为字符串,并将其输出回C中的标准输出

将标准输出捕获为字符串,并将其输出回C中的标准输出,c,redirect,stdout,C,Redirect,Stdout,使用C语言。我有一个函数可以写入标准输出 我想捕获这个输出,稍微修改一下(替换一些字符串)。然后再次将其输出到标准输出。所以我想从以下几点开始: char huge_string_buf[MASSIVE_SIZE]; freopen("NUL", "a", stdout); -OR- freopen("/dev/null", "a", stdout); setbuf(stdout, huge_string_buffer); /* modify huge_string_buffer */ 现在的

使用C语言。我有一个函数可以写入标准输出

我想捕获这个输出,稍微修改一下(替换一些字符串)。然后再次将其输出到标准输出。所以我想从以下几点开始:

char huge_string_buf[MASSIVE_SIZE];
freopen("NUL", "a", stdout); -OR- freopen("/dev/null", "a", stdout);
setbuf(stdout, huge_string_buffer);
/* modify huge_string_buffer */

现在的问题是,如何将巨大的字符串缓冲区输出回原始标准输出?

我真的不喜欢带有文件描述符的复杂游戏。你不能修改这个函数,让它以其他方式返回数据,而不是写入标准输出吗

如果您没有访问源代码的权限,并且您不能这样做,那么我建议将写入stdout的代码分解成一个单独的小程序,并作为另一个进程运行。重定向进程的输出(可能通过一个命名管道)是很容易和干净的,然后从接收数据的进程输出到stdout就没有问题了


此外,根据您希望进行的编辑类型,您最好使用像Python这样的高级语言来编辑数据。

Python有很好的方法来完成您想要的内容。但是如果你真的需要使用C,那么我会读一些C语言中的管道。。不过要小心,它们可能会很快变得非常复杂。

Unix实现这一点的方法实际上是编写一个小程序来执行所需的输入处理,然后通过命令行将另一个程序的输出传输到它

如果您坚持将所有内容都保存在C程序中,那么我要做的是重写该函数,让它将输出发送到给定的字符缓冲区(最好是
return
ing缓冲区的
char*
),以便可以将其发送到stdout,或者根据客户机的需要进行处理

例如,旧方法:

void usage () {
    printf ("usage: frob sourcefile [-options]\n");
}
…以及新的方式:

char * usage(char * buffer) {
    strcpy (buffer, "usage: frob sourcefile [-options]\n");
    return buffer;
}

一个想法是模仿标准Unix实用程序
tee
的功能,但完全在程序中进行,而不依赖外部重定向

因此,我编写了一个简单的函数,
mytee()
,它似乎可以工作。它使用了shmget()、pipe()、fork()和dup2():


有关这类内容的参考资料,请参见Dave Curry编写的《在Unix系统上使用C在O'Reilly上使用C》这本27年的优秀短文。

我已经用python完成了,但我需要将其重新集成到ANSI C中。因此除了调用另一个进程之外,没有其他方法了?我不确定我是否在某个地方违反了堆栈高度。是什么限制你使用C来实现这一点?一种更简洁的方法是将程序的输出通过过滤器传递,而不是执行所需的更改(假设命令行使用、操作系统支持管道等)。约束条件是微控制器上现有的构建和发布系统+运行时,我没有函数的源,它是从一个电话里打过来的。so@Stasik你有解决办法吗?我也有同样的问题,我运行ipmitool来获取一些信息,并希望修改内容,然后输出到stdout。我有ipmitool的代码,但我不想对代码做太多的更改,我最终将其包装在脚本中并进行文本处理there@Stasik-我建议把它写在回答中并接受它。我认为关于回答你自己的问题的限制性规定已经过了很久,它可能会帮助像查尔斯这样的人。
char huge_string_buf[MASSIVE_SIZE];
FILE stdout_ori=fdopen(stdout,"a");
freopen("NUL", "a", stdout); -OR- freopen("/dev/null", "a", stdout);
setbuf(stdout, huge_string_buffer);
/* modify huge_string_buffer */
//Write to stdout_fdopen
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>

static char *mytee(int size) {
   int shmid = shmget(IPC_PRIVATE, size + 1, 0660 | IPC_CREAT);
   int pipe_fds[2];
   pipe(pipe_fds);

   switch (fork()) {
      case -1:                      // = error
         perror("fork");
         exit(EXIT_FAILURE);
      case 0: {                     // = child
         char *out = shmat(shmid, 0, 0), c;
         int i = 0;
         out[0] = 0;
         dup2(pipe_fds[0], 0);      // redirect pipe to child's stdin
         setvbuf(stdout, 0, _IONBF, 0);
         while (read(0, &c, 1) == 1 && i < size) {
            printf("<%c>", c);      // pass parent's stdout to real stdout,
            out[i++] = c;           // and then buffer in mycapture buffer
            out[i] = 0;             // (the extra <> are just for clarity)
         }
         _exit(EXIT_SUCCESS);
      }
      default:                      // = parent
         dup2(pipe_fds[1], 1);      // replace stdout with output to child
         setvbuf(stdout, 0, _IONBF, 0);
         return shmat(shmid, 0, 0); // return the child's capture buffer
   }
}
int main(void) {
   char *mycapture = mytee(100);    // capture first 100 bytes
   printf("Hello World");           // sample test string
   sleep(1);
   fprintf(stderr, "\nCaptured: <%s>\n", mycapture);
   return 0;
}
<H><e><l><l><o>< ><W><o><r><l><d>
Captured: <Hello World>
  close(pipe_fds[0]);
  close(pipe_fds[1]);