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