Лучше, чем `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 code для обработки текста
  • Многострочная обработка текста: редактирование sshd_config
  • Печать регулярного выражения Sed в файл .txt
  • SED или AWK: добавьте символ в каждую строку после найденного шаблона
  • как подражать «замените abb a» на sed?
  • Сценарий Bash - части chomp из строки
  • Как найти строку после регулярного выражения в одной строке текста?
  • Grep текст, соответствующий шаблону
  • сценарий оболочки для извлечения символов
  • Скопируйте первые 2 строки из файла, а затем удалите строки
  • Interesting Posts
    Linux и Unix - лучшая ОС в мире.