캐리지 리턴을 사용하여 스팸 터미널의 출력 리디렉션

캐리지 리턴을 사용하여 스팸 터미널의 출력 리디렉션

초당 수백 줄 정도의 매우 자세한 출력을 생성하는 명령이 있습니다. 그러나 이 명령은 \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

col매우 원시 TTY-37 출력의 경우 이 명령은 M. Homer의 답변에 언급된 문제 없이 문제를 해결합니다 . (이것은 또한 sed단순 TTY-37이 아니고 터미널 이스케이프 및 제어 시퀀스를 포함하는 출력이 있는 작업을 위한 도구가 아닙니다 . 그러나 Stack Exchange에는colsed저것거의 8년이 지났습니다. )

%(
printf 'abcdefg\rxyz\n'
printf '123456789\r\nxyz\n'
)|열 b
xyz 정의
123456789
XYZ
%

답변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 = ""
}

Michael Homer의 예를 사용하면 다음과 같습니다.

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

이 변수에는 GNU awk가 필요하며 해당 레코드의 정규식 RT과 일치하는 레코드 구분 기호 텍스트를 포함합니다.RS

관련 정보