2

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

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

我的脚本 S 的参数之一是可选的;如果参数存在,它表示一个文件,它应该被输入到 P 中。如果参数缺失,S 的标准输入应该被输入到 P 中。

这是我尝试解决的问题:

P <${3:-&0}

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

P <foo

但如果它丢失或为空,它应该执行

P <&0

据我了解,这应该等同于简单地

P

即从标准输入读取。然而,这不起作用。在字面上使用 <&0 时,有效,如

echo abc|cat <&0

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

当然我可以使用这个技巧

cat $3|P

但这看起来不是很优雅。

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

4

1 回答 1

2

参数扩展发生在重定向之前,但这无济于事。<&0是操作符,而是操作符后跟被操作符解释为文件名的单词。如果文件名以.<&[NUMBER]<${…}<${…}<&

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

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

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

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

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

P () { … }
if [[ -n $3 ]]; then P <$3; else P; fi
于 2015-02-09T14:56:36.310 回答