web-dev-qa-db-ja.com

配管STDERRとSTDOUT

" Linux:The Complete Reference 6th Edition "(pg。44)によると、|&を使用して、onlySTDERRをパイプすることができますリダイレクト記号。

これをテストするためのかなり単純なスクリプトを作成しました。

#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2

このスクリプトは次のように実行します。

./script.sh |& sed 's:^:\t:'

おそらく、STDERRに出力される行だけがインデントされます。しかし、私が見るように、それは実際にはこのように機能しません:

    Normal Text.
    Error Text. 

ここで何が悪いのですか?

24
Naftuli Kay

あなたの本がどのテキストを使用しているのかはわかりませんが、 bash manual は明確です(すでにリダイレクトに慣れている場合)。

|&が使用されている場合、コマンド1の標準エラーは、その標準出力に加えて、パイプを介してコマンド2の標準入力に接続されます。 2>&1 |の短縮形です。この標準エラーから標準出力への暗黙的なリダイレクトは、コマンドで指定されたリダイレクトの後に実行されます。

したがって、標準出力と標準エラーを混在させたくない場合は、標準出力を別の場所にリダイレクトする必要があります。参照 標準エラーストリーム(stderr)をgrepする方法?

{ ./script.sh 2>&1 >&3 | sed 's:^:\t:'; } 3>&1

ただし、script.shおよびsedのfd 1と3はどちらも、元のstdout宛先を指します。善良な市民になりたい場合は、これらのコマンドに不要なfd 3を閉じることができます。

{ ./script.sh 2>&1 >&3 3>&- | sed 's:^:\t:' 3>&-; } 3>&1

bashおよびksh93は、>&3 3>&->&3-に圧縮できます(fd move)。

|&は、2>&1 |のようにstderrをstdinにパイプするため、次のプログラムはstdinで両方を取得します。

$cat test.sh
#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2
$./test.sh | sed 's:^:\t:'
Error Text.
        Normal Text.
$ ./test.sh |& sed 's:^:\t:'
        Normal Text.
        Error Text.
8
Kevin

bashの|&2>&1 |の(あまり移植性のない)ショートカットにすぎないため、すべての行がインデントされているはずです。

1
jw013