GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Nur STDERR durch einen Filter leiten

TL;DR:

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

Beispiel:

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

Dies funktioniert sowohl in bash als auch in zsh. Bash ist heutzutage jedoch ziemlich allgegenwärtig, wenn Sie wirklich eine (wirklich knorrige) Lösung für POSIX sh benötigen , dann siehe hier.

Erklärung

Der bei weitem einfachste Weg, dies zu tun, besteht darin, STDERR über die Prozesssubstitution umzuleiten:

Die Prozesssubstitution ermöglicht es, auf die Eingabe oder Ausgabe eines Prozesses unter Verwendung eines Dateinamens zu verweisen. Es hat die Form

>(list)

Die Prozessliste wird asynchron ausgeführt und ihre Eingabe oder Ausgabe erscheint als Dateiname.

Was Sie also mit der Prozesssubstitution erhalten, ist ein Dateiname.

So wie Sie es tun könnten:

$ cmd 2> filename

du kannst

$ cmd 2> >(filter >&2)

Die >&2 filter umleiten 's STDOUT zurück auf die ursprüngliche STDERR.


TL;DR:(bash und zsh)

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

Beispiel:

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

Viele Antworten im StackExchange-Netzwerk haben die Form:

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

Dies hat eine eingebaute Annahme:dass Dateideskriptor 3 nicht für etwas anderes verwendet wird.

Verwenden Sie stattdessen einen benannten Dateideskriptor und {ba,z}sh weist den nächsten verfügbaren Dateideskriptor>=10:

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

Beachten Sie, dass benannte Dateideskriptoren von POSIX sh nicht unterstützt werden .

Das andere Problem mit dem oben Gesagten ist, dass der Befehl nicht an weitere Befehle weitergeleitet werden kann, ohne STDOUT und STDERR wieder auf ihre ursprünglichen Werte zurückzusetzen.

Um die Weiterleitung in POSIX sh zu ermöglichen , (und immer noch davon aus, dass FD 3 nicht verwendet wird) wird es kompliziert:

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

Angesichts der Annahme und der knorrigen Syntax davon sind Sie wahrscheinlich besser dran, wenn Sie den einfacheren bash verwenden /zsh Syntax, die oben im TL;DR gezeigt und hier erklärt wird.

praktische Demonstration, gruppiert nur stderr:

$ 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

Hier ist ein Beispiel, das dem Austausch von Dateideskriptoren in bash nachempfunden ist. Die Ausgabe von a.out ist die folgende, ohne das Präfix '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

Zitat aus obigem Link:

  1. Speichern Sie zuerst stdout als &3 (&1 wird in 3 dupliziert)
  2. Sende als nächstes stdout an stderr (&2 wird in 1 dupliziert)
  3. Sende stderr an &3 (stdout) (&3 wird in 2 dupliziert)
  4. &3 schließen (&- wird in 3 überführt)

Eine naive Verwendung der Prozesssubstitution scheint das Filtern von stderr zu ermöglichen getrennt von stdout :

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

Beachten Sie, dass stderr erscheint auf stderr und stdout auf stdout , was wir sehen können, indem wir das Ganze in eine andere Subshell packen und auf die Dateien o umleiten und e

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

Linux
  1. 6 tcpdump-Filteroptionen für den Netzwerkverkehr

  2. Machen Sie Tail -f Exit auf einem kaputten Rohr?

  3. Wie schreibe ich stderr in eine Datei, während ich tee mit einer Pipe verwende?

  4. Wie drucke ich eine Nachricht an stderr in Go?

  5. Warum geht der Linux-Netzwerkverkehr nur über eth0?

So überwachen Sie den Fortschritt von Daten durch eine Pipe mit dem Befehl „pv“.

Neue Möglichkeit, Xargs über eine Pipe zu verwenden?

Ausgabe umleiten und leiten?

Wie leitet man Befehle an ein beliebiges Terminal weiter?

Abschluss abbrechen, aber nur Abschluss, in Zsh?

Rohr B nach D? – A &&B || C | D?