
다음과 같은 입력을 사용하여 파이프라인에서 "찾기"를 수행해 보세요.
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