파이프라인에서 STD{OUT,ERR}을 여러 번 교환

파이프라인에서 STD{OUT,ERR}을 여러 번 교환

기반으로이 답변, 파일 설명자 1과 2를 교환하기 위해 다음을 작성했습니다.

swap12:

#!/bin/bash
"$@" 3>&1 1>&2 2>&3 3>&-

그런 다음 파이프라인에서 STDERR을 작업할 수 있습니다. 예를 들면 다음과 같습니다.

$ swap12 ls -ld /tmp /ooooooo | tr o X
ls: cannXt access '/XXXXXXX': NX such file Xr directXry
drwxrwxrwt 19 root root 1400 Jul  1 17:14 /tmp

그러나 FD를 여러 번 교체하면 작동하지 않습니다.

$ swap12 ls -ld /tmp /ooooooo | swap12 tr o X | tr o Z
ls: cannXt access '/XXXXXXX': NX such file Xr directXry
drwxrwxrwt 19 root root 1400 Jul  1 17:14 /tmp

위에서는 두 번째가 swap12STDOUT과 STDRR을 다시 교환할 것으로 예상하므로 두 번째는 원래 STDOUT에서 작동합니다 tr. ls나는 다음을 보기를 고대하고 있다:

$ swap12 ls -ld /tmp /ooooooo | swap12 tr o X | tr o Z
ls: cannXt access '/XXXXXXX': NX such file Xr directXry
drwxrwxrwt 19 rZZt rZZt 1400 Jul  1 17:14 /tmp

내가 원하는 것을 어떻게 달성할 수 있나요?

내 문제는 서브셸에서 파일 설명자를 변경하여 발생한 것 같습니다. 전역 별칭 으로 zsh구현하면 이점이 있습니까 alias -g? (그러나 bash실제로는 어떤 모습일까요?)

답변1

일반적으로 stderr터미널로 직접 이동하여 stdout파이프를 입력하십시오.

          ls stdout -->
ls -ld /tmp /ooooooo | tr o X
 |
 v ls stderr (to terminal)

교체한 후 stdout파이프가 아닌 터미널로 이동합니다.

                 ls stderr -->
swap12 ls -ld /tmp /ooooooo | tr o X
        |
        v ls stdout

/ 교환은 이전에 파이프에서 리디렉션되었으므로 stdout어떤 방식으로든 결과를 포함하지 않습니다 .stderrtrstderrls

                 ls stderr -->   tr stderr -->
swap12 ls -ld /tmp /ooooooo | swap12 tr o X | tr o Z
        |                             |
        v ls stdout                   v tr stdout

stdoutstderr를 별도로 처리하려면 ls프로세스 대체를 사용할 수 있습니다(Bash 및 Zsh에서 작동해야 함).

$ ls -ld /tmp /ooooooo 2> >(tr o X)  > >(tr o Z) 
ls: cannXt access '/XXXXXXX': NX such file Xr directXry
drwxrwxrwt 25 rZZt rZZt 4096 Jul  1 14:40 /tmp/

답변2

파이프는 ls.stderr에 연결됩니다 tr1.stdin. 그런 다음 tr2 로 교환 tr1.stdout하고 tr1.stderr파이프하여 s 가 없음을 확인하므로 아무것도 하지 마십시오.tr1.stderrtr2.stdino

두 번째는 swap12첫 번째를 취소해서는 안 되며 앞으로도 취소하지 않을 것입니다.

이걸 할 건가요 ./swap12 ./swap12 ls -ld /tmp /ooooooo | tr o X? 이렇게 하면 스왑이 취소됩니다.

관련 정보