[linux] 필터를 통해 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

따라서 이것에 대한 가정과 문법을 감안할 때 위의 TL; DR에 표시된 더 간단한 bash/ zsh구문을 사용하는 것이 더 나을 입니다.


답변

bash 프로세스 대체의 사용은 원래 의도를 거의 그대로 반영하므로 기억하고 사용하기가 더 쉽습니다. 예를 들면 :

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

첫 번째 sed 명령을 stderr에서만 필터로 사용하고 두 번째 sed 명령을 사용하여 결합 된 출력을 수정합니다.

명령을 올바르게 구문 분석하려면 2> 뒤의 공백이 필수입니다.


답변

Advanced Bash Scripting Guide 의이 페이지 의 마지막 부분 은 “stderr 만 파이프로 리디렉션”입니다.

# stderr 만 파이프로 리디렉션합니다.

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.

# 감사합니다, SC

이것은 당신이 원하는 것일 수 있습니다. 그렇지 않다면 ABSG의 다른 부분이 당신을 도울 수있을 것입니다. 그것은 훌륭합니다.


답변

명명 된 파이프를 살펴보십시오.

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