今天我通过这篇文章学习有关 fifo 的知识:命名管道简介,其中提到cat <(ls -l)
.
我用 做了一些实验sort < (ls -l)
,弹出一个错误:
-bash: syntax error near unexpected token `('`
然后我发现我在命令中错误地添加了一个额外的空格。
但是,为什么这个额外的命令会导致这个失败呢?为什么重定向符号必须靠近(
?
答案1
因为那不是 a <
,而是<()
完全不同的 a 。这就是所谓的流程替代,它是某些 shell 的一项功能,允许您使用一个进程的输出作为另一个进程的输入。
和>
运算<
符重定向输出和输入文件。操作<()
员处理命令(进程),而不是文件。当你跑步时
sort < (ls)
您尝试ls
在子 shell 中运行该命令(这就是括号的含义),然后将该子 shell 作为输入文件传递到sort
.但是,这不是可接受的语法,您会收到所看到的错误。
答案2
因为事情本来就是这样的。
<(...)
inbash
是进程替换的语法。它是从 中的同一运算符复制的ksh
。
<
, (
, )
, |
, &
,;
是特殊的词汇标记,bash
用于形成不同组合的特殊运算符。<
、、、……<(
各有其作用。用于重定向。,将重定向文件中的输入。会重定向来自名为 的文件的输入,但它是一个不同的运算符,不是重定向运算符。<<
<&
<
<file
< file
<'(file)'
(file)
<(file)
< (file)
<
随后将是(file)
.在这种情况下, in bash
,(file)
无效。(...)
在某些上下文中可以作为单个令牌有效,例如:
(sub shell)
func () {
...
}
var=(foo bar)
但不是在
sort < (cmd)
在fish
外壳中,情况有所不同。 In fish
,(...)
用于命令替换(相当于$(...)
in bash
)。用于<
输入重定向,就像在类似 Bourne 的 shell 中一样。
所以在fish
:
sort <(echo file)
将与以下相同:
sort < (echo file)
那是:
sort < file
但这与bash
流程替换完全不同。
在yash
shell 中,另一个 POSIX shell,<(...)
不用于流程替代但对于进程重定向
在那里,
sort <(ls -l)
短缺:
sort 0<(ls -l)
是一个重定向运算符。它或多或少相当于:
ls -l | sort
在 中bash
,<(ls -l)
被扩展为管道的路径,所以它更像是:
ls -l | sort /dev/fd/0
在 中zsh
,(...)
被重载为 globbing 运算符((*.txt|*.png)
将扩展为txt
andpng
文件)和 glob 限定符(*(/)
例如扩展为目录文件)。
在zsh
,在:
sort < (ls -l)
这(ls -l)
将被视为全局限定符。 globl
限定符用于匹配链接数量,并期望后面有一个数字l
(如ls -ld ./*(l2)
列出具有 2 个链接的文件),因此这就是您zsh: number expected
在那里收到错误的原因。
sort < (w)
会给出一个zsh: no matches found: (w)
错误,因为(w)
与可写的空名称的文件相匹配。
sort < (w|cat)
将对当前目录中的w
和/或文件的内容进行排序...cat