zsh 重定向,连同参数扩展

zsh redirection, together with parameter expansion

我正在编写一个 shell 调用程序 P 的脚本 S。

P 只接受来自标准输入的输入。

我的脚本S有一个参数是可选的;如果参数存在,它表示一个文件,应该被送入P。如果参数丢失,S的stdin应该被送入P。

这是我尝试解决的问题:

P <${3:-&0}

想法是:如果(第 3 个)参数是文件名,比如:foo,它应该执行

P <foo

但如果缺少或为空,则应执行

P <&0

根据我的理解,这应该等同于

P

即从标准输入读取。但是,这不起作用。从字面上使用 <&0 时,可以工作,如

echo abc|cat <&0

它会产生错误消息 no such file or directory: &0 当以我在脚本中的方式使用时。这让我感到惊讶,因为我从 zsh 手册页中了解到参数扩展发生在设置重定向之前。

我当然可以使用这个技巧

cat |P

但这看起来不太优雅。

有人可以向我解释一下,为什么我的方法不起作用,在这里使用什么成语比较好?

参数扩展发生在重定向之前,但这没有帮助。 <&0<&<em>[NUMBER]</em> 运算符,而 <${…}< 运算符后跟${…} 运算符将 < 解释为文件名的单词。如果文件名以 &.

开头,则没有特殊情况会改变含义

您可以使用 exec 内置函数来设置重定向,而不是其他任何东西,以避免重复代码。当命令是外部命令时,这很有效。

( if [[ -n  ]]; then exec <; fi;
  exec P )

如果您需要 P 在外部上下文(而不是子 shell)中执行,另一种方法是使用中间文件描述符设置重定向。

if [[ -n  ]]; then exec 9<; else exec 9<&0; fi
P <&9
exec 9<&-

或者,定义一个函数以避免代码重复。

P () { … }
if [[ -n  ]]; then P <; else P; fi