Выходная сортировка | uniq в разделах, а не ждать полного ввода

Я использую sort и uniq для обработки вывода скрипта, т.е.

script | sort | uniq -c

Сценарий выводит данные порциями примерно по 1000 строк, затем выполняет дополнительную обработку и затем выводит еще 1000 строк. Части полностью независимы.

Мне было бы полезно иметь возможность обрабатывать вывод фрагментами по 1000 строк через sort и uniq и выводить результаты в консоль перед продолжением процесса.

Другими словами, я хочу, чтобы sort очищал свой буфер после обработки 1000 строк. Возможно ли это каким-либо образом?


person zelanix    schedule 16.04.2014    source источник
comment
Но, если бы это было возможно, вы бы сортировали только внутри каждого патрона...   -  person Roberto Reale    schedule 17.04.2014
comment
проблема не в буферизации, а в цели сортировки: она сортирует все строки стандартного ввода, поэтому приходится ждать последней, т.е. до EOF. для независимой сортировки каждого фрагмента вам придется разделить вывод script и передать его отдельным процессам sort. Как вы могли легко добиться этого с помощью bash, я не знаю   -  person Silly Freak    schedule 17.04.2014
comment
да, именно так, поэтому я хочу отсортировать каждый кусок по отдельности. Есть ли способ сломать трубу, чтобы эффективно вызвать EOF?   -  person zelanix    schedule 17.04.2014
comment
Это может быть 1000 строк или каждый раз одинаковое количество строк?   -  person John1024    schedule 17.04.2014
comment
да, это всегда будет одинаковое количество строк.   -  person zelanix    schedule 17.04.2014


Ответы (1)


Что-то вроде этого должно делать то, что вы хотите:

#!/bin/bash

while true; do
    i=0
    while IFS= read -r; do
        printf "%s\n" "$REPLY"
        if ((i >= 999)); then
            break
        fi
        ((i++))
    done > >(sort | uniq -c)
    if ((i==0)); then
        # previous `while read` returned no lines. We're done.
        break
    fi
done | cat

Это считывает до 1000 строк за раз со стандартного ввода и применяет sort | uniq -c для каждого блока из 1000 строк. Вы бы использовали это примерно так:

./yourscript | ./read1000.sh > output.txt

Прежде чем кто-нибудь назовет мне награду Бесполезное использование кота, этот cat необходим для синхронизации вывода из sort | uniq -c подстановки процесса, если вывод идет на терминал, а не перенаправляется в файл или канал.

person Digital Trauma    schedule 16.04.2014
comment
+1, хорошо сделано; вы, возможно, поместили его туда для ясности, но IFS= строго не требуется, так как $REPLY всегда получает всю строку, включая начальные и конечные пробелы (однако -r требуется, чтобы отключить интерпретацию управляющих последовательностей \ ). - person mklement0; 17.04.2014
comment
@mklement0 Я не знал этого о $REPLY. Спасибо! - person Digital Trauma; 17.04.2014
comment
Не за что; Я тоже не был уверен; Ваш ответ побудил меня исследовать проблему. - person mklement0; 17.04.2014
comment
@mklement0 mklement0 Я не смог найти упоминания об этом поведении $REPLY в руководстве по bash, хотя могу подтвердить, что ваше наблюдение определенно выдерживает проверку. Вы нашли это где-нибудь задокументировано? - person Digital Trauma; 17.04.2014
comment
Нет, я просто попробовал это, а именно в bash 3.2.51, 4.2.25 и 4.2.46, и поскольку все они ведут себя одинаково - и поведение, возможно, имеет смысл (необходимость по-прежнему использовать -r была для меня немного неожиданной ) — я предположил, что такое поведение останется; Вы правы, однако, все, что написано в руководстве, это If no names are supplied, the line read is assigned to the variable REPLY и его вариант. - person mklement0; 17.04.2014
comment
@mklement0 Я предполагаю, что источник является документация здесь ;-) См. комментарий, начинающийся со строки 756. - person Digital Trauma; 17.04.2014
comment
Отличная находка; Я никогда раньше не видел, как делают колбасу. - person mklement0; 17.04.2014
comment
Спасибо за отличный ответ! Я тоже многому научился из этого. - person zelanix; 18.04.2014