В APUE говорится, что «FIFO могут использоваться для дублирования выходного потока», но не говорится, что FIFO фактически дублируют выходной поток. Как вы заметили, в примере дублирование выполняется с помощью tee
.
mkfifo
создает FIFO, видимый как «файл» в содержащем каталоге; но запись в FIFO отличается от записи в файл, потому что данные никогда не попадают на диск. Каналы, названные или иные, не обеспечивают хранение данных, они обеспечивают каналы связи; записывающий конец канала не может записывать данные, если нет получателя, канал просто передает данные, не сохраняя их. (В большинстве систем каналы поддерживаются небольшими буферами ядра для повышения производительности, но это детали реализации.)
Линейные соединения между процессами представляют собой конвейеры, которые можно представить в виде линейного графа. В примере вы можете представить последнюю строку как
infile → prog1 → tee fifo1 → prog3
что линейно, но если попытаться представить всю цепочку, сводящуюся к обработке элементов, то нужно
infile → prog1 → prog2
→ prog3
который не является -линейным (в графе есть один узел, prog1
который имеет два выходных узла ).
sed -E "/^$/d" file | awk '/> Query/{printf "%s\t", $3; nr[NR+2]}; NR in nr '
Выход
TRINITY_DN109574_c0_g1_i1 ***** No hits found *****
TRINITY_DN109587_c0_g1_i1 ***** No hits found *****
TRINITY_DN109586_c0_g2_i1 Sequences producing significant alignments:
Прохождение...
Ваш идентификатор и расстояние между строками совпадений различаются в зависимости от того, получили вы попадание или нет, но расстояние меняется только с дополнительной пустой строкой, поэтому, если мы удалим все пустые строки
sed -E "/^$/d" file
то строка совпадения/не совпадения всегда находится на 2 строки впереди запроса. Затем мы передаем |
это в awk
, чтобы найти только те строки, которые являются началом запроса
awk '/> Query/'
но нам нужно только 3-е (разделенное пробелом )поле $3
из строки запроса, потому что это ваш идентификатор
awk '/> Query/{print $3}'
Всякий раз, когда мы находим соответствие регулярному выражению, мы также хотим вычислить номер строки совпадающей строки Hits и сохранить его в массиве. Я назвал массив nr
, а интересующая нас строка Hits — это текущая совпадающая строка NR
+2
awk '/> Query/{print $3; nr[NR+2]}'
Наконец, добавьте второе условие, чтобы проверить, существует ли в нашем массиве nr
строка NR
, которая не соответствует регулярному выражению, и распечатать ее. Также меняем первый print
на printf
, чтобы число попаданий выводилось в конце идентификатора.
awk '/> Query/{printf "%s\t", $3; nr[NR+2]}; NR in nr;'
Обратите внимание, что это решение не работает, если число, добавленное к NR
, не соответствует следующему регулярному выражению.
Используя GNU sed, мы накапливаем строки в пространстве шаблонов, начиная со строки запроса, продолжаем отбрасывать пустые строки и печатаем, когда накапливаются 3 непустые строки.
$ sed -e '
:loop
/\n.*\n/{
s//\t/
s/^> Query=//p
}
/^> Query=/!d
$d;N
s/\n$//
bloop
' file
В Perl мы глотаем файл и получаем строку запроса, пропускаем все пустые строки, пропускаем первую непустую строку
$ perl -0777ne 'print "$1\t$2" while /^> Query=\h+(.*)\n\n*.*\n\n*(.*\n)/mg' file
Используя GNU grep в режиме pcre, мы сначала извлекаем строку запроса, за которой следуют 2 непустые строки, промежуточные пустые строки могут варьироваться от нуля до нескольких.
$ < file grep -zoP '(?m:^> Query=\h+\K.*\n\n*(.*\n\n*){2})' |
tr -d '\0' | tr -s '\n' |
sed -e 'h;n;n;H;g;s/\n/\t/'
Другой метод с использованием оператора диапазона...
:
$ perl -lane '
$e = (/^> Query=/ && $c==0)... (/\S/ && $c==2);
next if !length($e) || !@F;
$q = $F[2] if $e == 1;
print "$q\t$_" if $e =~ /E0/;
$c = $c == 2 ? 0 : $c+1;
' file