如果这是一个基本问题,我深表歉意 - 我一直在尝试解决一个更大的问题,这取决于如何调用 shell 脚本 - 直接 ( shellScript.sh
) 或使用sh shellScript.sh
.
这是该问题的模型:
当我在 bash 上执行时:
cat <(echo 'Hello')
我看到输出
Hello
但是当我使用时:
sh -c "cat <(echo 'Hello')"
我看到错误:
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `cat <(echo 'Hello')'
我尝试过以各种组合转义<
,(
和)
,但我在任何地方都看不到输出。我在这里缺少什么?
我的实际问题是,我将 a<()
作为输入参数传递给 shell 脚本中的 python 脚本,虽然当我仅使用名称调用 shell 脚本时它工作正常,但如果我用来sh
调用它,我会收到类似的错误到我上面所展示的。
谢谢你!
答案1
进程替换是一项起源于 80 年代 Korn shell 的功能(首次记录在 ksh86 中)。当时,它仅适用于支持/dev/fd/<n>
文件的系统。
后来,该功能又被添加到zsh
(从1990年开始)和bash
(从1993年开始)。zsh
正在使用临时命名管道来实现它,而bash
正在使用/dev/fd/<n>
可用的地方和其他命名管道。1996 年zsh
改用/dev/fd/<n>
可用的地方。2.6-beta17
2012年/dev/fd
才添加了对通过命名管道在系统上进行进程替换的支持。的公共域克隆不支持它。ksh
ksh93u+
ksh
据我所知,没有其他类似 Bourne 的 shell 支持它(rc
、es
、fish
、非类似 Bourne 的 shell 支持它,但语法不同)。yash
有一个<(...)
构造,但那是为了进程重定向。
虽然非常有用,但该功能从未被 POSIX 标准化。因此,人们不能期望在 中找到它sh
,因此不应在sh
脚本中使用它。
尽管 POSIX 中未指定 的行为<(...)
(因此保留它不会有什么坏处),但在其环境中bash
调用 assh
或 with 时会禁用该功能。POSIXLY_CORRECT=1
因此,如果您有一个使用 的脚本<(...)
,则应该使用支持该功能的 shell 来解释它,例如zsh
、bash
或 AT&T ksh
(当然,您需要确保脚本的其余语法也与该 shell 兼容)。
任何状况之下:
cat <(cmd)
可以写成:
cmd | cat
要不就
cmd
cat
对于除(需要通过作为参数给出的文件传递数据)之外的命令,在具有 的系统上/dev/fd/x
,您始终可以执行以下操作:
something | that-cmd /dev/stdin
或者,如果您需要that-cmd
保留 的 stdin:
{ something 3<&- | that-cmd /dev/fd/4 4<&0 <&3 3<&-; } 3<&0