다른 명령의 입력을 분할하고 결과를 병합합니다.

다른 명령의 입력을 분할하고 결과를 병합합니다.

나는 다른 명령의 결과를 결합하는 방법을 알고 있습니다.

paste -t',' <(commanda) <(commandb)

동일한 입력을 다른 명령에 전달하는 방법을 알고 있습니다.

cat myfile | tee >(commanda) >(commandb)

이제 이러한 명령을 결합하는 방법은 무엇입니까? 그래서 나는 그것을 할 수 있다

cat myfile | tee >(commanda) >(commandb) | paste -t',' resulta resultb

나한테 파일이 있다고 해봐

내 파일:

1
2
3
4

새 파일을 만들고 싶어요

1 4 2
2 3 4
3 2 6
4 1 8

나는 사용했다

cat myfile | tee >(tac) >(awk '{print $1*2}') | paste

세로 방향의 결과를 얻으려면 가로 방향으로 붙여넣고 싶습니다.

답변1

여러 프로세스 대체를 수행할 때 특정 순서로 출력을 얻을 수 있다는 보장은 없으므로 다음을 고수하는 것이 좋습니다.

paste -t',' <(commanda < file) <(commandb < file)

값비싼 파이프를 표현한다고 가정하면 cat myfile출력을 파일이나 변수에 저장해야 한다고 생각합니다.

output=$( some expensive pipeline )
paste -t',' <(commanda <<< "$output") <(commandb <<< "$output")

귀하의 예를 사용하여 :

output=$( seq 4 )
paste -d' ' <(cat <<<"$output") <(tac <<<"$output") <(awk '$1*=2' <<<"$output")
1 4 2
2 3 4
3 2 6
4 1 8

또 다른 아이디어: FIFO와 단일 파이프

mkfifo resulta resultb
seq 4 | tee  >(tac > resulta) >(awk '$1*=2' > resultb) | paste -d ' ' - resulta resultb
rm resulta resultb
1 4 2
2 3 4
3 2 6
4 1 8

답변2

yash케이스에는 독특한 기능이 있습니다(파이프 리디렉션그리고프로세스 리디렉션) 일을 더 쉽게 하기 위해:

cat myfile | (
  exec 3>>|4
  tee /dev/fd/5 5>(commanda >&3 3>&-) 3>&- |
    commandb 3>&- |
    paste -d , /dev/fd/4 - 3>&-
)

3>>|4(파이프 리디렉션)는 fd 3에 쓰기 끝이 있고 fd 4에 읽기 끝이 있는 파이프를 만듭니다.

3>(commanda>&3)프로세스 리디렉션/dev/fd/n, ksh/zsh/bash 프로세스 교체와 유사하지만 . 로 교체하는 대신 리디렉션하는 것은 의 것과 거의 동일합니다 ksh( 사용자가 제어할 수 없는 파일 설명자 선택 ).>(cmd)yashn>(cmd) /dev/fd/nnksh

답변3

그리고 zsh:

pee() (
  n=0 close_in= close_out= inputs=() outputs=()
  merge_command=$1; shift
  for cmd do
    eval "coproc $cmd $close_in $close_out"

    exec {i}<&p {o}>&p
    inputs+=($i) outputs+=($o)
    eval i$n=$i o$n=$o
    close_in+=" {i$n}<&-" close_out+=" {o$n}>&-"
    ((n++))
  done
  coproc :
  read -p
  eval tee /dev/fd/$^outputs $close_in "> /dev/null &
    " exec $merge_command /dev/fd/$^inputs $close_out
)

그런 다음 다음과 같이 사용됩니다.

$ echo abcd | pee 'paste -d,' 'tr a A' 'tr b B' 'tr c C'
Abcd,aBcd,abCd

이것은 다음에서 적응되었습니다.이것은 또 다른 질문입니다거기에서 몇 가지 자세한 설명과 제한 사항에 대한 팁을 찾을 수 있습니다(교착 상태에 주의하세요!).

답변4

구체적인 예를 들어 paste나머지는 필요하지 않습니다. 표준 도구 세트의 한계에 부딪히는 경우가 종종 있는데, 이는 우리가 원하는 방식이 다른 방식으로 수행될 수 있기 때문입니다. 예를 들어:

set 1 2 3 4
while [ "$#" -gt 0 ]
do    echo "$1" "$#" "$(($1*2))"
shift;done

...인쇄...

1 4 2
2 3 4
3 2 6
4 1 8

"$@"다음과 같이 쉘 배열에서 언급한 내용이 포함된 파일을 얻을 수 있습니다 .

set -f; IFS='
'; set -- $(cat)

위와 같은 루프에서 arg 값을 확인하려면 초기 테스트를 약간 변경하면 됩니다.

while { [ "$1" -eq "${1-1}" ] ;} 2>&"$((2+!$#))"
do    echo "$1" "$#" "$(($1*2))"
shift;done  3>/dev/null >outfile

set -- $(cat)...읽은 행에 전체가 단일 정수로 구성되지 않은 행이 포함된 경우에만 stderr에 오류를 인쇄합니다.

관련 정보