Лучше, чем `tee | разрезать | … | paste`

Попытка выполнить «поиск» в конвейере, где ввод выглядит следующим образом:

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 wget | jq .

Важно: я хочу только один раз запустить процесс поиска.

а) это ужасная идея, и если да, то что я должен делать вместо этого?
б) есть лучшая картина, чем tee tmp | cut | "lookup" | paste tmp - tee tmp | cut | "lookup" | paste tmp - tee tmp | cut | "lookup" | paste tmp - ?

2 Solutions collect form web for “Лучше, чем `tee | разрезать | … | paste`”

Это зависит от того, насколько сложным является результат и сколько форматирования необходимо поддерживать (например, первый столбец всегда длиной 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 сохранял вывод в том же порядке, что и вход.

Вот простой пример 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 )) 

Правильный способ заключается в использовании именованного канала

Пример:

 function datastreamWrapper() { mypipe=$(mktemp -u) mkfifo -m 600 "$mypipe" tee >( cut -f2 | datastream ... > "$mypipe") | paste - "$mypipe" rm "$mypipe" } 

Затем вы можете поставить datastreamWrapper в свой конвейер:

 cat source.tab | datastreamWrapper | foo 
  • Печать регулярного выражения Sed в файл .txt
  • Найдите и замените строку, если определенный шаблон найден в строке
  • Заменить шаблон в файле с шаблоном во втором файле
  • Необходимо вставить одинарные кавычки в текстовый файл для использования в качестве SQL-запроса с помощью sed
  • Нежелательное совпадение с регулярным выражением SED (эмулировать perl's. *?)
  • Grep для нескольких строк, покажите количество строк после одной из строк (но не другой)
  • Удалить комментарии в файле C
  • Самый простой способ найти / заменить в файле с помощью списка?
  • распечатать определенную строку из нескольких файлов
  • Добавление строки в файл из удаленного ssh
  • Как добавить верхний и нижний колонтитулы в плоский файл
  • Linux и Unix - лучшая ОС в мире.