bash 中的管道继承优先级

时间:2021-07-10 15:18:48

标签: c bash shell pipe heredoc

我正在用 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)遇到定界符时才打印输出?

0 个答案:

没有答案