GNU/Linux >> Linux の 問題 >  >> Linux

STDERR のみをフィルタに通す

TL;DR:

$ cmd 2> >(stderr-filter >&2)

例:

% cat /non-existant 2> >(tr o X >&2)
cat: /nXn-existant: NX such file Xr directXry
%

これは、bash と zsh の両方で機能します。最近では Bash はかなり普及していますが、POSIX sh の (本当に危険な) ソリューションが本当に必要な場合は、

説明

これを行う最も簡単な方法は、プロセス置換を介して STDERR をリダイレクトすることです。

<ブロック引用>

プロセス置換により、プロセスの入力または出力をファイル名を使用して参照できます。

の形を取ります
>(list)

プロセス リストは非同期で実行され、その入力または出力はファイル名として表示されます。

したがって、プロセス置換で得られるのはファイル名です。

あなたができるように:

$ cmd 2> filename

できます

$ cmd 2> >(filter >&2)

>&2 リダイレクトの filter の STDOUT を元の STDERR に戻します。


TL;DR:(bash と zsh)

$ cmd 2> >(stderr-filter >&2)

例:

% cat /non-existant 2> >(tr o X >&2)
cat: /nXn-existant: NX such file Xr directXry
%

StackExchange ネットワーク上の多くの回答は次の形式をとっています:

cat /non-existant 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g'

これには、ファイル記述子 3 が他の目的で使用されていないという前提が組み込まれています。

代わりに、名前付きファイル記述子と {ba,z}sh を使用してください 次に利用可能なファイル記述子を割り当てます>=10:

cat /non-existant {tmp}>&1 1>&2 2>&$tmp {tmp}>&- | sed 's/e/E/g'

名前付きファイル記述子は POSIX sh ではサポートされていないことに注意してください .

上記のもう 1 つの問題は、STDOUT と STDERR を元の値に再度スワップしない限り、コマンドを別のコマンドにパイプできないことです。

POSIX sh で以降のパイプを許可するには 、(それでも FD 3 が使用されていないと仮定すると) 複雑になります:

(cmd 2>&1 >&3 3>&- | stderr-filter >&2 3>&-) 3>&1

したがって、この仮定と危険な構文を考えると、より単純な bash を使用する方がよいでしょう。 /zsh 上記の TL;DR に示され、ここで説明されている構文。

実用的なデモンストレーション、stderr のみを grep:

$ ls -l . noexistABC noexistXYZ
ls: cannot access 'noexistABC': No such file or directory
ls: cannot access 'noexistXYZ': No such file or directory
.:
total 4
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 bar.txt
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 foo.txt
drwxrwxr-x 2 frank frank 4096 Aug 19 12:26 someFolder


$ ( ls -l . noexistABC noexistXYZ 2>&1 >&3 3>&- | grep ABC >&2 3>&-) 3>&1
.:
ls: cannot access 'noexistABC': No such file or directory
total 4
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 bar.txt
-rw-rw-r-- 1 frank frank    0 Aug 19 12:26 foo.txt
drwxrwxr-x 2 frank frank 4096 Aug 19 12:26 someFolder

これは、 bash でファイル記述子を交換する方法をモデルにした例です。 a.out の出力は、'STDXXX:' 接頭辞なしで次のようになります。

STDERR: stderr output
STDOUT: more regular

./a.out 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g'
more regular
stdErr output

上記リンクより引用:

<ブロック引用> <オール>
  • 最初に stdout を &3 として保存します (&1 は 3 に複製されます)
  • 次に stdout を stderr に送信します (&2 は 1 に複製されます)
  • stderr を &3 (stdout) に送信します (&3 は 2 に複製されます)
  • &3 を閉じます (&- は 3 に複製されます)

  • プロセス置換の単純な使用により、 stderr のフィルタリングが可能になるようです stdout とは別に :

    :; ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 )
    out
    e:err
    

    stderr に注意してください stderr に出てくる と stdout stdout で 、全体を別のサブシェルでラップし、ファイル o にリダイレクトすることで確認できます と e

    ( ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 ) ) 1>o 2>e
    

    Linux
    1. 6tcpdumpネットワークトラフィックフィルターオプション

    2. パイプ全体でXargsを使用する方法はありませんか?

    3. リダイレクトとパイプ出力?

    1. Zshで、完了をキャンセルしますが、完了のみですか?

    2. エラーのみを表示するためにDmesgログをフィルタリングする方法は?

    3. 画面にStderrのみを表示しますが、StdoutとStderrの両方をファイルに書き込みますか?

    1. パイプでティーを使用しているときにstderrをファイルに書き込むにはどうすればよいですか?

    2. シェル:stdout を /dev/null にリダイレクトし、stderr を stdout にリダイレクトします

    3. Goでstderrにメッセージを出力するにはどうすればよいですか?