program tip

필터를 통해 STDERR 만 파이프

radiobox 2020. 11. 8. 09:43
반응형

필터를 통해 STDERR 만 파이프


bash에서 STDOUT과 통합하기 전에 필터를 통해 STDERR을 파이프하는 방법이 있습니까? 즉, 나는 원한다

STDOUT ────────────────┐
                       ├─────> terminal/file/whatever
STDERR ── [ filter ] ──┘

보다는

STDOUT ────┐
           ├────[ filter ]───> terminal/file/whatever
STDERR ────┘

다음 은 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

위 링크에서 인용 :

  1. 먼저 표준 출력을 & 3으로 저장합니다 (& 1은 3으로 속임)
  2. 다음으로 stdout을 stderr로 보냅니다 (& 2는 1로 속임)
  3. stderr을 & 3 (stdout)으로 전송 (& 3은 2로 속임)
  4. 닫기 & ​​3 (&-는 3으로 속임)

프로세스 대체의 순진한 사용은 다음과 stderr별도로 필터링을 허용하는 것 같습니다 stdout.

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

참고 stderr에 나오는 stderrstdoutstdout우리가 또 다른 서브 쉘에서 전체를 감싸고 파일로 리디렉션으로 볼 수있는, o그리고e

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

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원래 STDERR에의 STDOUT 백.


요약 : (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.

위의 다른 문제는 STDOUT 및 STDERR을 원래 값으로 다시 스왑하지 않으면 명령을 추가 명령으로 파이프 할 수 없다는 것입니다.

POSIX에서 진행되는 파이핑을 허용하려면 sh(그리고 여전히 FD 3이 사용되지 않는다고 가정) 복잡해집니다 .

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

So, Given the assumption and gnarly syntax of this, you're likely to be better off using the simpler bash/zsh syntax shown in the TL;DR above, and explained here.


I find the use of bash process substitution easier to remember and use as it reflects the original intention almost verbatim. For example:

$ cat ./p
echo stdout
echo stderr >&2
$ ./p 2> >(sed -e 's/s/S/') | sed 's/t/T/'
sTdout
STderr

uses the first sed command as a filter on stderr only and the second sed command to modify the joined output.

Note that the white space after 2> is mandatory for the command to be parsed correctly.


The last part of this page of the Advanced Bash Scripting Guide is "redirecting only stderr to a pipe".

# Redirecting only stderr to a pipe.

exec 3>&1                              # Save current "value" of stdout.
ls -l 2>&1 >&3 3>&- | grep bad 3>&-    # Close fd 3 for 'grep' (but not 'ls').
#              ^^^^   ^^^^
exec 3>&-                              # Now close it for the remainder of the script.

# Thanks, S.C.

This may be what you want. If not, some other part of the ABSG should be able to help you, it is excellent.


Take a look at named pipes:

$ mkfifo err
$ cmd1 2>err |cat - err |cmd2

참고URL : https://stackoverflow.com/questions/3618078/pipe-only-stderr-through-a-filter

반응형