由此命令行fu帖子:
$ diff <(wget -q -O - URL1) <(wget -q -O - URL2)
看起来像是多个标准输入,但如果我记得我的 Linux 编程课程没有错的话,这不可能。我认为,根据定义,标准输入是一个流。
也许这与 stdin 毫无关系?有人能给我解释一下吗?或者提供文档链接。
奖金:脚本如何处理这些多个流?如果有人可以提供 Python 或 Perl 示例,那将非常有帮助。
答案1
这不是多个标准输入。这是一种称为“进程替换”的 bash'ism http://tldp.org/LDP/abs/html/process-sub.html
它为每个替换创建一个伪文件 ( /dev/fd/something
)。它非常有用。该命令只能以流的形式读取,这意味着它不能使用 fseek 来回移动。它需要将其作为字节流读取,就像管道一样。
奖励答案
您不需要做太多事情就可以使用它。就您的脚本而言,它在命令行上获得一个有效的文件名,可以像其他任何东西一样打开它。正如其他人所说,你会看到diff /dev/fd/XX /dev/fd/YY
。如果您对这些伪文件中的任何一个执行 stat(),您将看到它是一个命名管道,并且您应该使用管道语义来处理它 - 即没有 fseek() 或 ftell()。如果您执行 stat() 测试以明确查看它是否是一个文件(例如[ -f $1 ]
),这将要中断——这毕竟是作为命名管道实现的。
答案2
<(...)
做流程替代在 bash 中。括号中进程的输出被发送到正常的 3 个文件描述符之外的附加文件描述符,并返回与该文件描述符相对应的文件名。这样,命令的输出可以被视为要传递给另一个命令的文件名。
答案3
有一stdin
,一stdout
对于每个过程。它们通常连接到终端,但可以彼此单独重定向。
在该示例中,涉及两个wget
进程,每个进程都有自己的stdin
和stdout
。每个wget
进程都将写入-
,即其stdout
。然后bash
,进程替换将进程的<(...)
连接stdout
到一个唯一的伪文件,diff
可以从中读取。请注意两个过程替换产生了两个不同的伪文件!因此,diff
看到类似这样的内容:
diff /dev/fd/XX /dev/fd/YY
其中连接到,stdout
的连接到。wget -q -O - URL1
/dev/fd/XX
stdout
wget -q -O - URL2
/dev/fd/YY