我对bash感到很自在,但是最近我以不知所措的方式结束了比赛。
<(<command>)
bash 到底是什么?它与=(<command>)
zsh中的相比如何?
我知道这与默认文件描述符有关。在我的电脑上
echo <()
return /proc/self/fd/11
,我发现它是脚本STDOUT的副本,但这对我来说仍然很混乱。
我对bash感到很自在,但是最近我以不知所措的方式结束了比赛。
<(<command>)
bash 到底是什么?它与=(<command>)
zsh中的相比如何?
我知道这与默认文件描述符有关。在我的电脑上
echo <()
return /proc/self/fd/11
,我发现它是脚本STDOUT的副本,但这对我来说仍然很混乱。
Answers:
这称为过程替换。
该<(list)
语法由两个支持,bash
和zsh
。list
当|
无法使用管道()时,它提供了一种将命令()的输出传递给另一个命令的方法。例如,当一个命令仅不支持来自以下命令的输入,STDIN
或者您需要多个命令的输出时:
diff <(ls dirA) <(ls dirB)
<(list)
将的输出list
与中的文件连接/dev/fd
(如果系统支持),否则将使用命名管道(FIFO)(这也取决于系统的支持;两本手册都没有说如果不支持这两种机制会发生什么,大概会中止)一个错误)。然后,在命令行上将文件名作为参数传递。
zsh
另外支持=(list)
尽可能替换<(list)
。与=(list)
临时文件一起使用,而不是使用文件/dev/fd
或FIFO。<(list)
如果程序需要在输出中查找,它可以用作替代。
根据ZSH手册,工作方式可能还存在其他问题<(list)
:
该
=
表单很有用,因为/dev/fd
和的命名管道实现<(...)
都有缺点。在前一种情况下,某些程序可能会在命令行上检查文件之前自动关闭有问题的文件描述符,尤其是出于安全原因(例如程序正在运行setuid时),这是必需的。在第二种情况下,如果程序实际上没有打开文件,则尝试从管道读取或写入管道的子外壳将永远处于阻塞状态(在典型的实现中,不同的操作系统可能具有不同的行为),并且必须明确终止。在这两种情况下,shell实际上都是使用管道来提供信息的,因此希望lseek(2)
在文件上查找的程序(请参见手册页)将无法工作。
注意,这是一个bash答案,而不是zsh。
在bash中,有些情况下您不能使用管道:
some_command | some_other_command
因为管道为管道的每个组件引入了子外壳,所以当子外壳退出时,您所依赖的任何副作用都会消失。例如,这个人为的例子:
cat file | while read line; do ((count++)); done
echo $count
将显示空白行,因为该$count
变量在当前shell中不存在。
bash 进程替代允许您像读取文件一样从“ some_command”输出中读取内容,从而避免了这一难题
while read line; do ((count++)); done < <(cat file)
# ....................................1.2
echo $count # the variable *does* exist in the current shell
(1)是正常的输入重定向。(2)是<()
流程替换语法的开始。
pfctl -f <(echo "pf rules")
会说错误的文件描述符。使用zsh和=(回显“ pf规则”)即可。