c - 如何在我的 shell 中实现管道和重定向?
问题描述
据我所知,有很多关于管道和文件重定向的信息。但我找不到任何关于同时进行管道和文件重定向的具体内容。如果有类似的东西我可能错过了,如果你不介意的话,请给我链接。
我想要做的是在 shell 中执行一个命令,这样就ls -l | grep total > test.txt
可以grep
从中获取总数ls -l
并将其输入test.txt
.
我有我的程序设置的方式,一切都被分解成 if() 逻辑来确定使用什么样的符号。这是我只为管道工作的内容,并且只为重定向工作。当我得到 a|
和 a时,我对如何继续进行有点困惑>
。我怎样才能将两者结合起来?
else if(pipey && !redirect)
{
char main_str[1024];
char pipe_str[1024];
char *left_args[100] = {NULL};
char *right_args[100] = {NULL};
strcpy(main_str, string);
int fd[2];
char *token = strchr(main_str, '|');
*token = '\0';
token++;
while(*token == ' ')
{
token++;
}
strcpy(pipe_str, token);
int i = 0;
for(token = strtok(main_str, " \n"), i = 0; token; token = strtok(NULL, " \n" ), ++i)
{
left_args[i] = token;
}
i = 0;
for(token = strtok(pipe_str, " \n"), i = 0; token; token = strtok(NULL, " \n" ), ++i)
{
right_args[i] = token;
}
if(pipe(fd) == -1)
{
return 2;
}
c1_pid = fork();
if(c1_pid < 0)
{
return 3;
}
if(c1_pid == 0)
{
dup2(fd[1], STDOUT_FILENO);
close(fd[0]);
close(fd[1]);
execvp(left_args[0], left_args);
}
c2_pid = fork();
if(c2_pid < 0)
{
return 4;
}
if(c2_pid == 0)
{
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
close(fd[1]);
execvp(right_args[0], right_args);
}
close(fd[0]);
close(fd[1]);
waitpid(c1_pid, NULL, 0);
waitpid(c2_pid, NULL, 0);
}
// A single redirect given by user
else if(!pipey && redirect)
{
char main_str[1024];
char pipe_str[1024];
char *left_args[100] = {NULL};
char *middle_args[100] = {NULL};
char *right_args[100] = {NULL};
strcpy(main_str, string);
char *token = strchr(main_str, '>');
*token = '\0';
token++;
while(*token == ' ')
{
token++;
}
strcpy(pipe_str, token);
int i = 0;
for(token = strtok(main_str, " \n"), i = 0; token; token = strtok(NULL, " \n" ), ++i)
{
left_args[i] = token;
}
i = 0;
for(token = strtok(pipe_str, " \n"), i = 0; token; token = strtok(NULL, " \n" ), ++i)
{
right_args[i] = token;
}
c1_pid = fork();
if(c1_pid < 0)
{
return 5;
}
if(c1_pid == 0)
{
int file = open(right_args[0], O_WRONLY | O_CREAT, 0777);
if(file == -1)
{
return 6;
}
dup2(file, STDOUT_FILENO);
execvp(left_args[0], left_args);
close(file);
}
waitpid(c1_pid, NULL, 0);
}
再次,只是想知道如何获取我目前拥有的东西,并将其应用于两个符号是否同时出现。所有解析的东西都很好,只是我有点不确定的管道和重复的东西。
解决方案
将这两个概念分成层次结构:
- 首先,管道由一个或多个通过管道链接在一起的命令组成:
command | command | command
. - 其次,命令由程序、其参数和任何重定向组成:
program arg1 arg2 arg3 >redirect1 2>redirect2 <redirect3
.
在一个函数中处理管道,在第二个从属函数中处理命令/重定向。
这将让您将这个单一的代码块分解成更小的部分。管道和重定向是正交的概念。它们属于单独的、独立的功能,因此它们不必相互了解。
您还应该将解析与执行分离。智能解耦对于将代码复杂性保持在可管理水平至关重要。
不要解析命令行并在同一代码块中执行子进程。将它们分开。执行字符串解析,提取相关部分,然后调用单独的函数来实际 fork/open/dup2/exec/waitpid。
推荐阅读
- html - 简单搜索字段在每个浏览器中的处理方式都不同
- metpy - 如何在metpy中将文本框添加到skew-t图中?
- java - 带有 MessagePack 的 Apache Beam - 如何从 Map 获取值
? - kubernetes - kubectl top 是当前内存/CPU 值吗?
- c++ - Crypto++ pbkdf2::DeriveKey() 的罕见崩溃
- laravel - Laravel 5:诊断密码重置令牌无效错误
- typescript - SyntaxError:使用 ES2015 模块导入和 jest 测试打字稿代码时出现意外的令牌导出
- python - 确定跨行的唯一字典键
- ios - (缩放)UITextView 上的变换动画
- c - 忽略scanf格式的空格