关于Bash中管道的工作原理,有什么简单的解释?

关于Bash中管道的工作原理,有什么简单的解释?,bash,pipe,Bash,Pipe,我经常在Bash中使用管道,例如: dmesg | less 虽然我知道这会输出什么,但它需要dmesg并允许我用更少的滚动它,但我不明白在做什么。它仅仅是>的反面吗 对于|的作用,是否有一个简单的或隐喻性的解释 在一条管线中使用多条管道时会发生什么 管道的行为在Bash脚本中出现的任何地方都是一致的吗 管道操作符获取第一个命令的输出,并通过连接stdin和stdout将其“管道”到第二个命令。 在您的示例中,dmesg命令的输出不是发送到stdout(并将其发送到控制台),而是直接发送到下

我经常在Bash中使用管道,例如:

dmesg | less
虽然我知道这会输出什么,但它需要
dmesg
并允许我用
更少的
滚动它,但我不明白
在做什么。它仅仅是
>
的反面吗

  • 对于
    |
    的作用,是否有一个简单的或隐喻性的解释
  • 在一条管线中使用多条管道时会发生什么
  • 管道的行为在Bash脚本中出现的任何地方都是一致的吗

管道操作符获取第一个命令的输出,并通过连接stdin和stdout将其“管道”到第二个命令。
在您的示例中,dmesg命令的输出不是发送到stdout(并将其发送到控制台),而是直接发送到下一个命令

Unix管道将第一个进程的STDOUT(标准输出)文件描述符连接到第二个进程的STDIN(标准输入)。然后发生的情况是,当第一个进程写入其标准输出时,第二个进程可以立即读取该输出(从标准输入)

使用多个管道与使用单个管道没有什么不同。每个管道都是独立的,只是将相邻进程的标准输出和标准输入链接起来

你的第三个问题有点模棱两可。是的,管道本身在bash脚本中的任何地方都是一致的。但是,管道字符
|
可以表示不同的内容。例如,双管道(
|
)表示“或”运算符。

  • |
    将左侧命令的STDOUT置于右侧命令的STDIN

  • 如果您使用多个管道,它只是一个管道链。第一个命令输出设置为第二个命令输入。第二个命令输出设置为下一个命令输入。等等

  • 它在所有基于Linux/widows的命令解释器中都可用


Unix中的每个标准进程至少有三个文件描述符,它们有点像接口:

  • 标准输出,即进程打印其数据的位置(大部分时间是在控制台,即您的屏幕或终端)
  • 标准输入,即它获取数据的位置(大多数情况下,它可能类似于键盘)
  • 标准误差,即误差和有时其他带外数据出现的位置。现在这并不有趣,因为管道通常不会处理它
管道将左侧流程的标准输出连接到右侧流程的标准输入。您可以将其视为一个专用程序,负责复制一个程序打印的所有内容,并将其提供给下一个程序(管道符号后面的程序)。不完全是这样,但这是一个足够的类比

每个管道只运行两件事:左边的标准输出和右边的输入流。其中每一个都可以附加到单个进程或管道的另一位,这在多管道命令行中就是如此。但这与管道的实际操作无关;每个管道都有自己的功能


重定向操作符(
)执行一些相关但更简单的操作:默认情况下,它将进程的标准输出直接发送到文件。正如你所看到的,它不是管道的对立面,而是互补的。与
相反的是
管道获取进程的输出,我所说的输出是指标准输出(
stdout
在UNIX上),并将其传递到另一个进程的标准输入
(stdin)
。它不是简单的右重定向的相反,右重定向的目的是将一个输出重定向到另一个输出

例如,以Linux上的echo命令为例,它只是在标准输出上打印传入参数的字符串。如果使用以下简单重定向:

echo "Hello world" > helloworld.txt
shell将重定向最初打算在stdout上的正常输出,并将其直接打印到文件
helloworld.txt

现在,以管道为例:

ls-l| grep helloworld.txt

ls
命令的标准输出将在grep输入时输出,那么这是如何工作的呢


grep
这样的程序在没有任何参数的情况下使用时,只是在读取并等待在其标准输入
(stdin)
。当grep捕获到诸如ls命令的输出之类的内容时,它会通过查找正在搜索的内容来正常工作。

如果将每个unix命令视为一个独立的模块,
但是,您需要他们使用文本作为一致的界面进行交谈,
怎样才能做到呢

cmd                       input                    output

echo "foobar"             string                   "foobar" 
cat "somefile.txt"        file                     *string inside the file*
grep "pattern" "a.txt"    pattern, input file      *matched string*
你可以说,
|
是接力马拉松中传递接力棒的隐喻。
它的形状甚至像一个
cat->echo->less->awk->perl
类似于
cat | echo | less | awk | perl

cat“somefile.txt”| echo

cat
将其输出传递给
echo
使用

当有多个输入时会发生什么情况?
cat“somefile.txt”| grep“pattern”


对于
grep


通过经验,您将慢慢发展了解哪个参数是哪个参数的眼光。

管道非常简单,如下所示

您有一个命令的输出。可以使用管道将此输出作为另一个命令的输入。可以根据需要使用管道传输任意多个命令

例: ls | grep my | grep文件

首先列出工作目录中的文件。该输出由grep命令检查单词“my”。该命令的输出现在进入第二个grep命令,该命令最终搜索单词“files”。就这样

    > program_1 | program_2 | ... | program_n
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
    int     fd[2], nbytes;
    pid_t   childpid;
    char    string[] = "Hello, world!\n";
    char    readbuffer[80];

    pipe(fd);

    if((childpid = fork()) == -1)
    {
            perror("fork");
            exit(1);
    }

    if(childpid == 0)
    {
            /* Child process closes up input side of pipe */
            close(fd[0]);

            /* Send "string" through the output side of pipe */
            write(fd[1], string, (strlen(string)+1));
            exit(0);
    }
    else
    {
            /* Parent process closes up output side of pipe */
            close(fd[1]);

            /* Read in a string from the pipe */
            nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
            printf("Received string: %s", readbuffer);
    }

    return(0);
}
> program_1 | program_2 | program_3