2

プログラム P を呼び出すシェルスクリプト S を書いています。

P は stdin からの入力のみを受け入れます。

私のスクリプト S のパラメーターの 1 つはオプションです。パラメータが存在する場合、それは P に供給されるべきファイルを示します。パラメータが欠落している場合、S の標準入力が P に供給されるべきです。

これはそれを解決するための私の試みでした:

P <${3:-&0}

アイデアは次のとおりです。(3番目の)パラメーターがファイル名の場合、たとえばfoo、実行する必要があります

P <foo

ただし、見つからないか空の場合は実行する必要があります

P <&0

私の理解では、これは単に

P

つまり、標準入力から読み取ります。ただし、これは機能しません。<&0 を文字通り使用している間、次のように機能します

echo abc|cat <&0

スクリプトで実行している方法で使用すると、エラー メッセージno such file or directory: &0が生成されます。これは私を驚かせます.zshのmanページから、リダイレクトを設定する前にパラメーターの展開が発生することを理解しています。

もちろん、私はトリックを使うことができました

cat $3|P

しかし、これはあまりエレガントに見えません。

なぜ私のアプローチがうまくいかなかったのか、ここで使用するのに適したイディオムは何ですか?

4

1 に答える 1

2

パラメータ展開はリダイレクトの前に発生しますが、それは役に立ちません。<&0は演算子ですが、 は演算子の後に、演算子がファイル名として解釈する単語が続きます。ファイル名が で始まる場合、意味が変わる特別なケースはありません。<&[NUMBER]<${…}<${…}<&

コードの重複を避けるために、ビルトインを使用execしてリダイレクトのみを設定できます。これは、コマンドが外部コマンドの場合にうまく機能します。

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

(サブシェルではなく) 外部コンテキストで実行する必要がある場合の別の方法Pは、中間ファイル記述子を使用してリダイレクトを設定することです。

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 に答える