将标准输出捕获为字符串,并将其输出回C中的标准输出
使用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 */ 现在的
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]);