関数を呼び出すbashスクリプトがあります。とりわけ、この関数は出力を受け取るパイプを実行します。簡単にするために、以下は人為的な例です。
#!/bin/bash
func() {
ls "$@" | sort | rev > /tmp/output
}
func "$@"
次に、実行するためにそのようなタスクを実行します。そのアクションを実行し、ペイロードをファイルに渡します。画面に出力がありません。
$ ./myscript .
sort
それでは、出力を標準出力として欲しいとしましょう。どうすればいいですか?
私はこれを次のように達成できます。
ls "$@" | sort | tee /dev/tty | rev > /tmp/output
しかし、以下を/dev/tty
使用するのは間違っています。
$ ./myscript > myfile
関数内のパイプ内でbashスクリプトの標準出力を参照するより正しい方法はありますか?
(私はArch Linuxでbash 4.3.0を使用しています)
答え1
私が考えることができる最も簡単な方法は次のとおりです。
ls "$@" | sort | tee >(rev > /tmp/output)
tee
コピーはSTDOUTに転送され、その後にaがなくなったため、|
これが継承されます。つまり、リダイレクトがない場合はTTYに移動し、myfile
そうであればTTYに移動します。別のコピーが対応するSTDIN
に送信されます。rev > /tmp/output
Bashでは、>(...)
括弧の間のすべてのエントリが実行され、>(...)
STDINに接続されたパイプパスに置き換えられます。
答え2
これに対する他の答えは明確ではないので、別の(代替)アプローチは次のとおりです。
exec 3>&1
ls | sort | tee /dev/fd/3 | rev > /tmp/output
これexec 3>&1
繰り返すファイル記述子1(stdout)をファイル記述子3として指定します。その後、出力コピーが対応するファイルtee /dev/fd/3
記述sort
子に書き込まれます。これはすべてのシェルで機能しますが、オペレーティングシステムによって異なる場合があります。 OS独立でなければなりませんが、bash
OSに固有のバリエーションは次のとおりです。
exec 3>&1
ls | sort | tee >( cat >&3 ) | rev > /tmp/output
はbash
、実行中のプロセスのパイプを指すファイルハンドルを提供します。>(command)
command
。どの (?) シェルで次を実行します。command >&fd
command
標準出力は、以前に設定されている必要がある指定されたファイル記述子にリダイレクトされます。
すべての*nix(Posix)システムで動作するより洗練されたバージョンは次のとおりです。
pipe_to_stdout=$(mktemp -u)
mkfifo "$pipe_to_stdout"
cat "$pipe_to_stdout" &
ls | sort | tee "$pipe_to_stdout" | rev > /tmp/output
rm "$pipe_to_stdout"
これは2番目の例(fifoで読み込んでstdoutに書き込む)とほぼ同じですcat
が、シェルレベルでは煙とミラーが少なくなります。
ls
これらの答えは、出力を標準出力に書き込むようにコマンドを簡単に並べ替えることができるという点で柔軟です。