为什么`sort <(ls -l)` 有效,而`sort < (ls -l)` 失败?

Zen*_*Zen 32 bash process-substitution

今天我通过这篇文章学习了一些关于 fifo 的东西:命名管道简介,其中提到了cat <(ls -l).

我使用 做了一些实验sort < (ls -l),它弹出一个错误:

-bash: syntax error near unexpected token `('`
Run Code Online (Sandbox Code Playgroud)

然后我发现我在命令中错误添加了一个额外的空格。

但是,为什么这个额外的命令会导致这个失败呢?为什么重定向符号必须靠近(?

ter*_*don 45

因为那不是<,而是<()完全不同的。这称为进程替换,它是某些 shell 的一项功能,允许您将一个进程的输出用作另一个进程的输入。

在>与<运营商输出重定向到输入的文件。该<()运营商的命令(进程)的交易,而不是文件。当你跑

sort < (ls)
Run Code Online (Sandbox Code Playgroud)

您正在尝试ls在子 shell 中运行命令(这就是括号的意思),然后将该子shell 作为输入文件传递给sort. 然而,这是不被接受的语法,你会得到你看到的错误。

  • 您的回答很好,但是`then sort 试图将子shell 作为其输入文件读取` → 这显然是错误的,因为 Bash 甚至不会解析语法。`ls` 和 `sort` 都没有实际运行。 (3认同)

Sté*_*las 22

因为这就是它本来的样子。

<(...)inbash是进程替换的语法。它是从ksh.

<, (, ), |, &,;是特殊的词法标记bash,用于形成不同组合的特殊运算符。<, <(, <<, <&... 各有各的作用。<用于重定向。<file,< file将从文件重定向输入。<'(file)'将从名为 的文件重定向输入(file),但它<(file)是一个不同的运算符,不是重定向运算符。

< (file)将<紧随其后(file)。在这种情况下,在bash,(file)是无效的。(...)在某些情况下可以作为单个令牌有效,例如:

(sub shell)
func () {
  ...
}
var=(foo bar)
Run Code Online (Sandbox Code Playgroud)

但不是在

sort < (cmd)
Run Code Online (Sandbox Code Playgroud)

在fish外壳中,它是不同的。In fish,(...)用于命令替换(相当于$(...)in bash)。并且<用于像 Bourne-like shell 中的输入重定向。

所以在fish:

sort <(echo file)
Run Code Online (Sandbox Code Playgroud)

将与:

sort < (echo file)
Run Code Online (Sandbox Code Playgroud)

那是:

sort < file
Run Code Online (Sandbox Code Playgroud)

但这与 的bash过程替换完全不同。

在yashshell 中,另一个 POSIX shell<(...)不是用于进程替换而是用于进程重定向

在那里,

sort <(ls -l)
Run Code Online (Sandbox Code Playgroud)

短缺:

sort 0<(ls -l)
Run Code Online (Sandbox Code Playgroud)

是重定向操作符。它或多或少相当于:

ls -l | sort
Run Code Online (Sandbox Code Playgroud)

在 中bash,<(ls -l)扩展到管道的路径,所以它更像是:

ls -l | sort /dev/fd/0
Run Code Online (Sandbox Code Playgroud)

在zsh,(...)被重载为通配符((*.txt|*.png)将扩展为txt和png文件)和通配符(*(/)例如扩展为目录文件)。

在zsh,在:

sort < (ls -l)
Run Code Online (Sandbox Code Playgroud)

这(ls -l)将被视为全局限定符。该l水珠预选赛是要匹配的链接数,并预计之后的数l(如ls -ld ./*(l2)将列出与2个链接中的文件),所以这就是为什么你会得到一个zsh: number expected错误出现。

sort < (w)会给出一个zsh: no matches found: (w)错误,因为(w)匹配具有可写空名称的文件。

sort < (w|cat)会对当前目录中的w和/或cat文件的内容进行排序...