
Я использую инструмент ( openocd
), который печатает много мусора, затем базовый индикатор выполнения, медленно печатающий простые точки, затем снова какой-то мусор.
Я хотел бы отфильтровать этот вывод так, grep
чтобы отображалась только строка с индикатором выполнения, причем в режиме реального времени (т.е. каждая выведенная точка openocd
немедленно выводилась в терминале):
openocd <args> |& grep '^\.'
Проблема в том, что grep
строка буферизуется (в лучшем случае), поэтому индикатор выполнения не будет отображаться, пока она не будет завершена.
Как мне сделать с grep
, или есть ли стандартная альтернатива для достижения этого? Если есть способ через openocd
конфигурацию, это было бы полезно, хотя я бы предпочел более общее решение.
решение1
Это своего рода хакерский/необычный ответ, поскольку, скорее всего, это возможно не совсем чистым способом.
grep
сам по себе, похоже, выводит вывод только при обнаружении символа новой строки, ваш индикатор выполнения, вероятно, не вводит символ новой строки при обновлении, отсюда и ваша проблема.
strace
— это инструмент, используемый для просмотра системных вызовов, вызываемых командой. Сюда входят такие операции, как чтение и запись в память/хранилище, а также открытие/закрытие файловых дескрипторов.
С strace
вы можете просмотреть, к чему обращается процесс, в случае, если ваш канал stout
передается в grep
, поэтому с strace
вы можете просмотреть текст, который передается в grep
. strace
будет регулярно отправляться вывод, поступающий из переданной по каналу команды, и вы можете прослушать этот вывод и отобразить его. Я тестировал с rsync --progress
, который, похоже, сталкивается с похожим сценарием. Я использовал grep
на , ##%
потому что это то, что rsync
используется для отображения прогресса.
rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%"
Если вы запустите эту команду, то обнаружите, что она strace
не дает хорошего вывода, но когда я ее использовал, она strace
поймала пару read
s из , rsync
которые grep
обычно не появляются write
, показывая read
s для 0%, 21%, 45%, 68%, 91% и 100%, и, похоже, обновлялась примерно каждую секунду (вероятно, исходя из того, как часто rsync
обновляется прогресс).
Таким образом, с помощью этого можно получить не очень приятный grep
вывод strace
, вызвав то же самое grep
снова.
rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%" 2>&1 > /dev/null | grep -o "[0-9]*%"
Важно 2>&1
, потому что strace
печатает на stderr
. > /dev/null
Перенаправляет stdout
на , /dev/null
чтобы предотвратить вывод первого, grep
который будет сообщен. Конечным результатом этого был следующий вывод:
0%
21%
45%
68%
91%
100%
Вам придется заменить grep
, но, похоже, это сработает. Это некрасиво, но это работает и обходит ограничения grep
. Кажется, что , grep -f
который работает как , tail -f
был бы удобен (я знаю, grep -f
что уже используется).
Первый вариант grep
в основном нужен для фильтрации текста, который strace
будет отображаться, поскольку в вызовах s read
будут перечислены только соответствующие строки , но вам также нужно что-то, через что будет проходить текст, чтобы вы могли его отслеживать.strace
read
strace
решение2
Я трачу деньги на ответ в Centimane, так как окончательный ответ довольно сложен.
Это и так было довольно халтурно... теперь это становится действительно паршиво:
make flash \
|& strace -e trace=read grep -e "^\." -e rror \
|& stdbuf -o0 sed -ne 's/^.*"\.".*/\./p;/rror/p' \
| stdbuf -o0 tr -d '\n' \
; echo
Итак, make flash
вышеизложенное — это призыв openocd
;
strace
использует описанный выше взлом Centimane;
sed
заменить read(0, ".", xxx)
строки на одинарные .
;
tr
сохраняет все .
на одной строке, а окончательное эхо ставит единственный EOL.
В дополнение к этому, вызываются sed
и , которые устанавливают размер буфера stdout в 0 (так как удален конец строки), а также сопоставляются для вывода некоторого мусора в случае ошибки.tr
stdbuf -o0
grep/sed
(e)rror
Я попытался свести все это раздувание к минимуму, но не смог добиться большего.
Обратите внимание, что я использую zsh/Ubuntu 14.04 и не уверен, что это будет работать на других Unix.