Перенаправление вывода, который засоряет терминал возвратами каретки

Перенаправление вывода, который засоряет терминал возвратами каретки

У меня есть команда, которая создает очень подробный вывод, порядка сотен строк в секунду. Однако команда использует \rдля перезаписи предыдущей строки вывода, подобно полосе прогресса. Иногда она записывает новую строку в терминал, что «запекает» текущую строку вывода.

При перенаправлении этого вывода в файл я получаю сотни мегабайт вывода — каждая строка записывается в файл, а не «перезаписывается» при возврате каретки.

Я понимаю, что это ожидаемое поведение, и что один из способов решения этой проблемы — сделать программу умнее и осознать, что она перенаправляется в файл, а не выводить этот интерактивный статус. Однако я не могу изменить эту программу.

Есть ли способ передать/отфильтровать этот вывод так, чтобы в конечном выходном файле оказалось то же самое, что я увидел бы, запустив его в интерактивном режиме на терминале?

Я пробовал:

spammy_cr_command | uniq

... который выводит то же самое, что и без негоuniq

а также:

spammy_cr_command | sed '/\r/d'

... который также удаляет «запеченные» строки, содержащие символ новой строки.

решение1

cmd | sed -e 's/.*\r//' > file

Это заменит весь текст в каждой строке, за которой следует возврат каретки, ничем, оставив только часть строки после последнего возврата каретки. Это необязательното же самое, что осталось бы на терминале, но в большинстве случаев это близкое к истине значение.


В частности, случай, когда строка длиннее, чем ее последующая строка, не обрабатывается. Эта программа даст неверные результаты:

printf 'abcdefg\rxyz\n'
printf '123456789\r\nxyz\n'

потому что то, что останется после себя, это будет видно

xyzdefg
123456789
xyz

но он sedтакже пропустит все нестертые символы и даст

xyz

xyz

Вы можете определить, ведет ли себя ваша программа так или нет. Нередко бывает так, что индикаторы выполнения и т. п. оставляют курсор на левом краю, что может не дать желаемого результата.

решение2

Для очень примитивного вывода TTY-37 colкоманда решает эту проблему без проблем, sedупомянутых в ответе М. Гомера. (Для вывода, который не является простым выводом TTY-37 и содержит последовательности выхода терминала и управления, ни , colни не sedявляются инструментом для этой работы; но на Stack Exchange был вопрос и ответ начто(В течение почти восьми лет.)

%(
printf 'abcdefg\rxyz\n'
printf '123456789\r\nxyz\n'
) | кол -б
xyzdefg
123456789
хyz
%

решение3

Нечто более близкое к поведению перезаписи можно реализовать с помощью GNU awk:

BEGIN { 
  RS = "[\r\n]"                   # split records on either CR or LF
  a = ""                          # variable to save the text for overwriting
} 
{
  a = $0 substr(a, 1 + length)    # save current line, add trailing part of saved text
} 
RT ~ /\n/ {                       # LF, time to print and reset
  print a;
  a = ""
}

Используя пример Майкла Гомера:

~ awk 'BEGIN { RS="[\r\n]" } {a = $0 substr(a, 1 + length)} RT ~ /\n/ {print a; a=""}' foo
xyzdefg
123456789
xyz

RTДля переменной, содержащей текст разделителя записей, соответствующий RSрегулярному выражению для этой записи, необходим GNU awk .

Связанный контент