【クイズ】現実逃避のためのSTDOUT, STDERR 〜その2〜
ここ が前回。
クイズ〜その1〜
[bash]
$ perl -e ‘print "1\n" ; warn "2\n";'
[/bash]
これですが、普通に
[bash]
$ 1
$ 2
[/bash]
と表示されるだけです。まあ別に問題ない。
クイズ〜その2〜
[bash]
$ perl -e ‘print "1\n" ; warn "2\n";’ >a.txt
[/bash]
これですが、
[bash]
$ 2
[/bash]
となります。
1 がどこに消えたかというと、
[bash]
$ cat a.txt
[/bash]
で出てきます。
この結果の違いは、標準出力と標準エラー出力の違いのためです。
標準出力は、画面への出力、または、次のコマンドに対して標準入力
のどちらかとなります。
それに対して、標準エラー出力は、ユーザの目に見える形に直接出力します。
図で見る
[bash]
$ perl -e ‘print "1\n" ; warn "2\n";'
[/bash]
の場合を見てみると…
となるので、両方ともディスプレイに表示されます。
次は、grepを使ってみます。
[bash]
$ perl -e ‘print "1\n" ; warn "2\n";’ | grep 1
[/bash]
とした場合です。
この場合の挙動は
[bash]
$ 2
$ 1
[/bash]
となり、さっきとは逆の出力となります。
これを表した図が下のものです。
2 が先に出力されているのは、図の状況のためです。
標準エラー出力は、パイプによって grep
に渡されないので、直接ディスプレイに出力された。
一方、標準出力はパイプによって、 grep
に標準入力とされた。その後ディスプレイに出力された。
そんなわけで、
a.txt に 1 が記述されていて、
プロンプトには 2 が出力された、と。
標準出力と標準エラー出力っていうのは別々で出力しているんだよ、っていうお話です。
2>&1
ちなみに、標準出力も標準エラー出力も同じファイルに出力したい…という時は
[bash]
$ perl -e ‘print "1\n" ; warn "2\n";’ >a.txt 2>&1
[/bash]
とします。
1 が標準出力
2 が標準エラー出力を挿しています。
>a.txt も
1>a.txt も同じ意味です。
2>&1 は「2の出力先を1の出力先と同じにする」という意味を持っています。
注意
注意する点としては、
1>a.txt 2>&1
と
2>&1 1>a.txt
は違います。
前者は
1 の出力先を a.txt と設定し、
2 の出力先を 1 と同じにする。
つまり、
1 の出力先 a.txt
2 の出力先 a.txt
です。
後者は
2 の出力先を 1 と同じとして、
1 の出力先を a.txt と設定する。
つまり、
1 の出力先 a.txt
2 の出力先 default (ディスプレイ)
となります。
きっかけ
そもそもなぜこんなことをしているかというと、
いい加減、>/dev/null
2>&1と書くのをやめたらどうか (追記あり)
ここを見たからです。
[bash]
$ perl -e ‘print "1\n" ; warn "2\n";’ 1>a.txt 2>a.txt
[/bash]
について少し悩みましたが、「よく考えればそりゃそうだ」っていう結論。頭が固い…。
ていうか
ぐぐれば速攻出てきたので、考えたのは一体なんだったのか状態…。
まあ、パズルみたいで楽しかったです。
卒論の現実逃避にもなりましたし。
最後に
[bash]
$ perl -we
‘syswrite(STDERR,"1\n");syswrite(STDOUT,"2\n");syswrite(STDOUT,"3\n");syswrite(STDERR,"4\n")’
> a.txt 2> a.txt
[/bash]
が分かりませんでした。
そもそも、卒論中でちゃんと考えきれていないので、これから考えていきます。
3>&-
とか
4>&1
とかも今後…。
ぐぐりたくないでござる。
しばらく考えて分からなければ、周りに聞いて、それでダメなら、ぐぐってみます。