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

为什么?

这看起来像是 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

相关内容

最新更新