我正在用 C 编写我自己的 bash 版本。目前,当它通过管道传输到另一个命令时,我坚持复制heredoc 行为。 我已经参考了 bash 文档 (https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Here-Documents),但没有找到任何关于如何执行管道 heredoc 的优先级的信息。
在 bash 中,命令 cat << hi | echo 123
首先将输入作为 heredoc 扫描到 cat
,然后将它累积的所有内容重定向到 echo
(不读取任何输入),然后 {{ 1}} 被打印出来。
我的shell的当前版本,在执行相同的命令时,首先写入123
,同时通过heredoc将输入扫描到123
中。
所以 bash:
cat
我的外壳:
bash-3.2$ cat << hi | echo 123
> a
> b
> c
> hi
123
我的管道代码:
MyShell$ cat << hi | echo 123
> 123
a
> b
> c
> hi
a
b
c
我的 heredoc 代码:
static int substitution_in(t_ast *node, int fd_redirect[2])
{
int child_pid;
child_pid = fork();
if (child_pid == 0)
{
close(fd_redirect[1]);
dup2(fd_redirect[0], 0);
close(fd_redirect[0]);
node->exec(node);
exit(1);
}
return (child_pid);
}
static int substitution_out(t_ast *node, int fd_redirect[2])
{
int child_pid;
child_pid = fork();
if (child_pid == 0)
{
close(fd_redirect[0]);
dup2(fd_redirect[1], 1);
close(fd_redirect[1]);
node->exec(node);
exit(1);
}
return (child_pid);
}
static int pipe_exec(t_ast *self)
{
int fd_redirect[2];
int left_pid;
int right_pid;
pipe(fd_redirect);
right_pid = substitution_out(self->right, fd_redirect);
left_pid = substitution_in(self->left, fd_redirect);
close(fd_redirect[0]);
close(fd_redirect[1]);
waitpid(right_pid, NULL, 0);
waitpid(left_pid, NULL, 0);
return (0);
}
我阅读了这一行,将其拆分为标记,并构建了一个抽象语法树。 令牌列表如下所示:
static void heredoc(char *delimeter, int env_subst_needed, int *fd_here)
{
char *line_read;
line_read = readline("> ");
while (strcmp(line_read, delimeter))
{
if (env_subst_needed)
handle_envs(&line_read);
write(fd_here[1], line_read, strlen(line_read));
write(fd_here[1], "\n", 1);
line_read = readline("> ");
}
}
static int two_left_redir(t_ast *self)
{
char *delimeter;
int env_subst_needed;
int fd_redirect[2];
char *line_read;
restore_original_file_descriptors();
delimeter = self->left->data;
env_subst_needed = !has_quotes(delimeter);
resect_quotes_from_line(&delimeter);
pipe(fd_redirect);
heredoc(delimeter, env_subst_needed, fd_redirect);
close(fd_redirect[1]);
dup2(fd_redirect[0], 0);
close(fd_redirect[0]);
return (0);
}
AST 如下所示:
Token value: cat
Token value: <<
Token value: "hi"
Token value: |
Token value: echo
Token value: 123
为什么heredoc第一个扫描输入?为什么第二个命令只有在第一个命令(heredoc)遇到定界符时才打印输出?