How to write from stdin to a pipe in C
我有一个被参数调用的程序:
1 | pipeline -f outfile2 < infile > outfile1 |
它应该模仿bash脚本的功能:
1 | (rev | sort | uniq -c | tee outfile2| wc) < infile > outfile1 |
我了解如何设置管道,但不了解如何进行初步阅读。 我已经将outfile2文件名捕获到一个变量中,但是我认为可以保留外部两个文件,并且操作系统会将它们分别作为stdin和stdout来选择。 如何在父进程中以编程方式将stdin读入管道?
UPDATE之后:以下代码不使用命令行参数修改输出文件:pipeline -f outfile2 outfile1
显然带有真实文件名。
主要:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | char *fp; int c; /* parse command line arguments */ parse_argv(argc, argv); if (pipe(pipeOne) == -1){ /* Create the pipe */ perror("pipe one"); error(-1); } if (pipeOne[1] != 1){ dup2(pipeOne[1], stdout); exit(-1); } while ((c = getc(stdin)) != EOF){ if ((write(pipeOne[1], c, 1)) < 1) { perror("Write to pipe failed."); exit(-1); } } wc_child(); /* begin reading file to pipe */ if (close(pipeOne[0]) == -1){ /* Close unused read end */ perror("closing pipes"); exit(-1); } close (pipeOne[1]); |
wc_child:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | void wc_child(){ int numread; switch (fork()) { /* Create a child process */ case -1: perror("fork for rev_child"); case 0: /* Child */ /*if (close(pipeOne[1]) == -1) /* Close unused write end */ /*perror("closing pipes");*/ if (close(pipeOne[1]) == -1){ /* Close unused write end */ perror("closing pipes"); exit(-1); } dup2(pipeOne[0], stdin); /* dup2(pipeFive[0], stdin);*/ /* Not sure how to set up stdout since it will be going to a file.*/ for(;;){ execlp("wc","wc"); } break; default: /* Parent */ return 0; } return -1; /*return -1 because it never should reach this code. If it does that indicates a problem*/ } |
您可以
不过,我认为您真的不想做任何事情。而不是从
您可以使用很多不同的方法来完成此操作。使用
1 2 3 4 5 6 7 8 9 10 11 |
为了模拟管道,您实际上不需要将任何内容从标准输入复制到管道。您只需让
这是从我对C Minishell的回答中快速得出的代码-添加满足您需求的管道。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | /* ** How to write from stdin to a pipe in C ** https://stackoverflow.com/questions/19826211 ** ** Write program pipeline to be invoked as: ** ** pipeline -f outfile2 < infile > outfile1 ** ** It should mimic the functionality of the bash script: ** ** (rev | sort | uniq -c | tee outfile2 | wc) < infile > outfile1 ** ** Refactored, with equivalent functionality: ** ** rev < infile | sort | uniq -c | tee outfile2 | wc > outfile1 ** ** Based on answer to SO 13636252 C Minishell adding pipelines */ /* pipeline.c */ #include #include <errno.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/wait.h> #include <unistd.h> /* who | awk '{print $1}' | sort | uniq -c | sort -n */ static char *cmd0[] = {"rev", 0 }; static char *cmd1[] = {"sort", 0 }; static char *cmd2[] = {"uniq","-c", 0 }; static char *cmd3[] = {"tee", 0, 0 }; static char *cmd4[] = {"wc", 0 }; static char **cmds[] = { cmd0, cmd1, cmd2, cmd3, cmd4 }; static int ncmds = sizeof(cmds) / sizeof(cmds[0]); static char const usestr[] ="[-f filename]"; typedef int Pipe[2]; /* These functions normally declared in stderr.h */ static void err_setarg0(const char *argv0); static void err_sysexit(char const *fmt, ...); static void err_syswarn(char const *fmt, ...); static void err_usage(char const *usestr); /* exec_nth_command() and exec_pipe_command() are mutually recursive */ static void exec_pipe_command(int ncmds, char ***cmds, Pipe output); /* With the standard output plumbing sorted, execute Nth command */ static void exec_nth_command(int ncmds, char ***cmds) { assert(ncmds >= 1); if (ncmds > 1) { pid_t pid; Pipe input; if (pipe(input) != 0) err_sysexit("Failed to create pipe"); if ((pid = fork()) < 0) err_sysexit("Failed to fork"); if (pid == 0) { /* Child */ exec_pipe_command(ncmds-1, cmds, input); } /* Fix standard input to read end of pipe */ dup2(input[0], 0); close(input[0]); close(input[1]); } execvp(cmds[ncmds-1][0], cmds[ncmds-1]); err_sysexit("Failed to exec %s", cmds[ncmds-1][0]); /*NOTREACHED*/ } /* Given pipe, plumb it to standard output, then execute Nth command */ static void exec_pipe_command(int ncmds, char ***cmds, Pipe output) { assert(ncmds >= 1); /* Fix stdout to write end of pipe */ dup2(output[1], 1); close(output[0]); close(output[1]); exec_nth_command(ncmds, cmds); } /* Execute the N commands in the pipeline */ static void exec_pipeline(int ncmds, char ***cmds) { assert(ncmds >= 1); pid_t pid; if ((pid = fork()) < 0) err_syswarn("Failed to fork"); if (pid != 0) return; exec_nth_command(ncmds, cmds); } /* Collect dead children until there are none left */ static void corpse_collector(void) { pid_t parent = getpid(); pid_t corpse; int status; while ((corpse = waitpid(-1, &status, 0)) != -1) { fprintf(stderr,"%d: child %d status 0x%.4X\ ", (int)parent, (int)corpse, status); } } int main(int argc, char **argv) { int opt; char *filename ="outfile2"; // Default file name err_setarg0(argv[0]); while ((opt = getopt(argc, argv,"f:")) != -1) { switch (opt) { case 'f': filename = optarg; break; default: err_usage(usestr); break; } } if (optind != argc) err_usage(usestr); /* Set the file name for tee to write to */ cmd3[1] = filename; exec_pipeline(ncmds, cmds); corpse_collector(); return(0); } /* Normally in stderr.c */ static const char *arg0 ="<undefined>"; static void err_setarg0(const char *argv0) { arg0 = argv0; } static void err_usage(char const *usestr) { fprintf(stderr,"Usage: %s %s\ ", arg0, usestr); exit(1); } static void err_vsyswarn(char const *fmt, va_list args) { int errnum = errno; fprintf(stderr,"%s:%d:", arg0, (int)getpid()); vfprintf(stderr, fmt, args); if (errnum != 0) fprintf(stderr," (%d: %s)", errnum, strerror(errnum)); putc('\ ', stderr); } static void err_syswarn(char const *fmt, ...) { va_list args; va_start(args, fmt); err_vsyswarn(fmt, args); va_end(args); } static void err_sysexit(char const *fmt, ...) { va_list args; va_start(args, fmt); err_vsyswarn(fmt, args); va_end(args); exit(1); } |
输出示例(
1 | 125 691 4879 |
输出示例(
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 22 1 )... ,tmf* tsnoc rahc(nrawsys_rre diov citats 1 )... ,tmf* tsnoc rahc(tixesys_rre diov citats 1 )0 < ))(krof = dip(( fi 1 )0 < ))(krof = dip(( fi 1 )0 =! )tupni(epip( fi 1 )0 =! dip( fi 1 )0 =! munrre( fi 1 )0 == dip( fi 1 )0vgra* rahc tsnoc(0grates_rre diov citats ... 1 >h.tressa< edulcni# 1 C ni epip a ot nidts morf etirw ot woH ** 1 eman elif tluafeD // ;"2eliftuo" = emanelif* rahc 1 senilepip gnidda llehsiniM C 25263631 OS ot rewsna no desaB ** 10 { 3 { 2 { 10 } 3 } 2 } |
(我注意到,无论行是否反转,字数都是相同的,因此