Bashでは、パイプラインの中間ノードの結果をどのように計算してキャプチャしますか?
たとえば、単一のBashパイプを使用して整数リストとコマンドまたは関数を指定した場合、リストを標準出力に出力しながら変数内のmaximum
整数リストの最大値をどのようにキャプチャできますか?
capture_maximum_and_print_numbers
以下のBashスクリプトでは、関数を単一のパイプになるように変更することがアイデアです。
function maximum {
awk 'NR==1||$0>x{x=$0}END{print x}'
}
function capture_maximum_and_print_numbers {
local numbers="3\n6\n1\n4\n2\n9\n5\n"
maximum=$(printf $numbers | maximum)
printf $numbers
}
capture_maximum_and_print_numbers
printf "maximum=$maximum\n"
答え1
結果を厳密に変数に代入し、数値リストを1行の標準出力に出力する場合は、次のようなものを提供します。 (私はmax関数の名前を関数の機能に合わせて変更し、変数は保存された$maximum
結果自体に対応します):
function calc_max {
awk 'NR==1||$0>x{x=$0}END{print x}'
}
function capture_maximum_and_print_numbers {
local numbers="3\n6\n1\n4\n2\n9\n5\n"
export maximum=$(printf $numbers | tee /dev/tty | calc_max)
}
capture_maximum_and_print_numbers
echo max_result="$maximum"
#You have stored the max_result variable and can pass it to whatever you want.
tee
長いコマンドパイプラインの途中で、「現在」の結果を別のファイルに保存したり、標準出力に出力したりするなどの操作に使用できます。単一のパイプラインを別々のターゲットを持つ複数のコピーに分割し、同時に「プライマリ」パイプラインをチェーンの下に処理し続けます。
tee dev/tty
tty
現在の端末のパイプに対応し、/dev/tty
すべての* nixシステムに表示されます。
答え2
#!/bin/sh
generate_data () {
shuf -i 0-1000 -n 10 -r
}
print_maximum () {
awk 'NR == 1 || m < $0 { m = $0 } END { print m }'
}
exec 3>&1
maximum=$(
generate_data |
tee /dev/fd/3 |
print_maximum
)
exec 3>&-
printf 'maximum = %d\n' "$maximum"
これは任意の数を渡し、tee
ファイル記述子3とstdoutにコピーしますtee
。標準出力は、print_maximum
生成された数字のうち最大の数字を見つけて出力するように読み込まれます。
ファイル記述子3は、最初にシェルの標準出力ストリームのコピーとして開かれ(使用されます)、exec 3>&1
これはファイルtee
記述子がに書き込まれると(書き込みによって/dev/fd/3
)データがシェルの標準出力に表示されることを意味します。ファイル記述子は後で閉じられます(使用済みexec 3>&-
)。
このスクリプトでは/bin/sh
bash-isms を使用する必要がないため、bash-isms を使用します。それにもかかわらず、ファイル記述子3として機能し、システム提供のパスに依存しないことがbash
保証されます。/dev/fd/3
例を実行してください:
$ sh script
918
787
290
998
737
1000
845
374
497
809
maximum = 1000
grep
すべての出力がスクリプトの標準出力から生成されることを示すために、生成されたデータが可能であることを示すことができます。
$ sh script | grep -F 0
100
807
maximum = 807
$ sh script | grep -F 0
440
207