stdinがfd4にリダイレクトされた場合、読み取りが機能するのはなぜですか?

stdinがfd4にリダイレクトされた場合、読み取りが機能するのはなぜですか?

次のスクリプトはどういう意味ですか?

exec 4<&0 0</etc/XX/cfg
read line1
exec 0<&4

fd0をfd4にリダイレクトし、「/etc/XX/cfg」をfd0にリダイレクトします。

では、なぜそれreadでも動作しますか?空にしてはいけませんか?

答え1

これはstdin(FD0)をFD4にリダイレクトし、FD0を/etc/XX/cfgFD0にリダイレクトし、FD0から行を読み取り、FD4を再びFD0に移動します。つまり、中間ファイルから 1 行を読みながら標準入力を保存、置換、復元します。

read line1 < /etc/XX/cfgはるかに簡単ですが、表示されたコードだけが有効な代替であるかどうかを知る方法はありません。

答え2

Cを使用してシステムコールに再キャストするには:

exec 4<&0 0</etc/XX/cfg

/* Duplicate fd0 as fd4.  */
dup2 (0, 4);

/* Open file on fd0.
   "open" always uses lowest available descriptor, so we don't need to check it. */
close (0);
open ("/etc/XX/cfg", O_RDONLY);

exec 0<&4

/* Close fd0 and duplicate fd4 as fd0.  */
dup2 (4, 0);

答え3

私がこれを読む方法は、--bashのマニュアルページのリダイレクトセクションに基づいて-(fd0)をfd4にリダイレクトし、入力を受けてstdin最終的にfd4に到達することです。/etc/XX/cfgstdin

read line1その後、fd4から取り出してfd0に戻す必要があります。

デモでは、私が何を意味するのかをよりよく説明し、これを行う「理由」に答えることができます。別の行を追加してラッパーに入れると、次のようになります。

$ vim ./test.sh
#!/bin/bash
exec 4<&0 0</etc/XX/cfg
read line1    # reads from fd4
exec 0<&4
read line2    # reads from fd0

echo $line1 
echo $line2

test.shを介してパイプまたはリダイレクトすることはできますが、stdinリダイレクトを介して設定を読み取ることもできるため、上記のコードでは "config"から値を抽出しました(ファイル名に基づいていると仮定しました。悪い)。また、stdinを介して処理します。

たとえば、

$ ./test.sh < somefile
$ cat somefile | ./test.sh

これが説明されることを願っています。

関連情報