bash:在流程替换中使用大括号括弧式翻译时,歧义重定向

时间:2019-04-20 01:39:17

标签: bash

以下人为设计的示例起作用:

$ while read -r line; do echo $line; done < <(ls -al *.js)
...

但是,以下给出了错误:

$ while read -r line; do echo $line; done < <(ls -al {package.json,package-lock.json})
-bash: 0: ambiguous redirect

尽管流程替换中的内容工作正常:

$ ls -al {package.json,package-lock.json}
-rw-r--r--  1 me  staff   764K Apr 19 10:23 package-lock.json
-rw-r--r--  1 me  staff    10K Apr 19 10:23 package.json

那是为什么?

1 个答案:

答案 0 :(得分:4)

这看起来像bash v3中的错误(或至少是怪异的),但已在v4中修复。发生的事情是,括号扩展({package.json,package-lock.json})被应用于整个流程替换,而不仅仅是其中的一个参数。这是一个简化的示例,我将用它来演示正在发生的事情:

$ cat < <(echo {a,b})
-bash: 0: ambiguous redirect

让我们尝试一下它的一些变体:

$ cat <(echo {a,b})    # This works, sort of... each arg winds up on a separate line
a
b
$ echo <(echo {a,b})    # echo shows *two* different process substitutions are being done
/dev/fd/63 /dev/fd/62
$ grep -H . <(echo {a,b})    # This prints where it gets each line, showing it gets one letter/line from each substitution
/dev/fd/63:a
/dev/fd/62:b

...因此,看起来<(echo {a,b})正在括号内扩展到<(echo a) <(echo b),而不是<(echo a b)。这适用于catgrep,因为它们接受多个输入文件,但是<重定向只能接收一个输入文件(因此会出现“歧义重定向”错误)。

这似乎在bash v4中已修复(我已经在v4.2.10和4.4.19中进行了测试):

$ echo $BASH_VERSION 
4.4.19(1)-release
$ cat < <(echo {a,b})
a b
$ cat <(echo {a,b})
a b
$ echo <(echo {a,b})
/dev/fd/63