'티'보다 붙여넣는 더 나은 방법 |

'티'보다 붙여넣는 더 나은 방법 |

다음과 같은 입력을 사용하여 파이프라인에서 "찾기"를 수행해 보세요.

alice  5
bob    7
...

데이터베이스의 두 번째 열에서 코드를 찾아서 해당 이름을 반환하고 원본 데이터와 찾은 데이터를 계속 배송하고 싶습니다.

cat source.tab | \
  tee foo.tmp | \
  cut -f 2 | \
  dbstream ... -s "select(select name from my_lookup where code=?)" | \
  paste foo.tmp -

결과는 다음과 같습니다.

alice  5  foo
bob    7  bar
...

이것이 cat source.tab실제로 추가 전처리를 수행하는 긴 파이프라인이라고 상상해 보세요. 이는 dbstream ..다른 명령일 수 있습니다(예: ) wget | jq.

중요: 검색 프로세스는 한 번만 시작하고 싶습니다.

a) 이것이 나쁜 생각인가요? 그렇다면 어떻게 해야 합니까?
b) 이보다 더 나은 모델이 있습니까 tee tmp | cut | "lookup" | paste tmp -?

답변1

이는 출력의 복잡성과 유지해야 하는 형식의 정도에 따라 달라집니다(예: 첫 번째 열의 길이는 항상 8자입니까? 등). 그러나 while루핑은 작동할 수 있습니다.

cat source.tab | while read -r name id
do
  echo "$name $id $(dbstream .... code=$id)"
done

루프 내부에서 일어나는 일을 변경하여 원하는 대로 형식을 지정할 수 있습니다.

cat source.tab | while read -r name id
do
  res=$(dbstream ... code=$id)
  printf "%10s %5d %s" $name $id $res
done

리뷰에 따르면 한 번만 전화하고 싶습니다 dbstream. 이를 위해서는 dbstream출력을 입력과 동일한 순서로 유지해야 합니다.

다음은 간단한 예제 dbstream프로그램입니다:

#!/bin/sh
for a in "$@"
do
  echo dbstream $$ sees $a
done

PID를 출력에 포함시켜 한 번만 호출된다는 것을 보여줄 수 있습니다.

이제 paste대체를 사용하고 처리할 수 있습니다.

$ paste source.tab <(./dbstream $(awk '{print $2}' source.tab ))
alice 1 dbstream 20671 sees 1
bob   2 dbstream 20671 sees 2

이제 source.tab프로세스가 느린 경우 임시 파일을 사용하는 것이 좋습니다.

예를 들어

#!/bin/bash

tmp=`mktemp`

trap '/bin/rm -f $tmp ; exit' 0 1 2 3 15

cat source.tab > $tmp
paste $tmp <(./dbstream $(awk '{print $2}' $tmp ))

답변2

올바른 방법은 명명된 파이프를 사용하는 것 같습니다.

예:

function datastreamWrapper() {

  mypipe=$(mktemp -u)
  mkfifo -m 600 "$mypipe"

  tee >( cut -f2 | datastream ... > "$mypipe") | paste - "$mypipe"

  rm "$mypipe"
}

그런 다음 datastreamWrapper를 파이프라인에 넣을 수 있습니다.

cat source.tab | datastreamWrapper | foo

관련 정보