34

(BASH の場合) サブシェルで非 STDOUT 非 STDERR ファイル記述子を使用して、一部のデータを親シェルに戻す必要があります。どうやってやるの?最終的には、データを親シェルの変数に保存したいと思います。

(
  # The following two lines show the behavior of the subshell.
  # We cannot change them.
  echo "This should go to STDOUT"
  echo "This is the data I want to pass to the parent shell" >&3
)
#...
data_from_subshell=... # Somehow assign the value of &3 of the
                       # subshell to this variable

編集: サブシェルは、STDOUT および &3 に書き込むブラックボックス プログラムを実行します。

4

2 に答える 2

33

BEWARE, BASHISM AHEAD (there are posix shells that are significantly faster than bash, e.g. ash or dash, that don't have process substitution).

You can do a handle dance to move original standard output to a new descriptor to make standard output available for piping (from the top of my head):

exec 3>&1 # open 3 to the same output as 1
run_in_subshell() { # just shortcut for the two cases below
    echo "This goes to STDOUT" >&3
    echo "And this goes to THE OTHER FUNCTION"
}

Now you should be able to write:

while read line; do
    process $line
done < <(run_in_subshell)

but the <() construct is a bashism. You can replace it with pipeline

run_in_subshell | while read line; do
    process $line
done

except than the second command also runs in subshell, because all commands in pipeline do.

于 2013-03-01T10:06:09.757 に答える
6

もちろん、最も簡単な方法は、親で直接出力をキャプチャすることです

data_from_subshell=$(echo "This is the data I want to pass to the parent shell")

子からデータを読み取る別の方法として、名前付きパイプを使用できます

mkfifo /tmp/fifo

これで、子をにリダイレクトできます/tmp/fifo

(
    echo "This should go to STDOUT"
    echo "This is the data I want to pass to the parent shell" >/tmp/fifo
) &

そして親はそこから読むことができます

read data_from_subshell </tmp/fifo

別の方法はcoproc、子プロセスを開始するために使用することです。これにより、双方向パイプを持つ子が作成され、子のstdinとstdoutがパイプ記述子にリダイレクトされます。子でパイプとstdoutの両方を使用するには、最初に親でstdoutを複製する必要があります

exec 4>&1 # duplicate stdout for usage in client

coproc SUBSHELL (
    exec 3>&1 1>&4- # redirect fd 3 to pipe, redirect fd 1 to stdout
    (
    echo "This should go to STDOUT"
    echo "This is the data I want to pass to the parent shell" >&3
    )
)

exec 4>&- # close fd 4 in parent
read data <&${SUBSHELL[0]}
echo "Parent: $data"

コプロセスはBash4.0で導入されました。

于 2013-03-01T09:13:37.330 に答える