「ティー」よりも貼り付けるより良い方法

「ティー」よりも貼り付けるより良い方法

次の入力を使用してパイプラインで「検索」を実行します。

alice  5
bob    7
...

データベースの2番目の列でコードを見つけてその名前を返し、元のデータと見つかったデータを引き続き出荷したいと思います。

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

関連情報