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
위 링크에서 인용 :
- 먼저 표준 출력을 & 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
답변
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