스크립트 출력에서 ​​제어 문자 (콘솔 코드 / 색상 포함) 제거


68

"script"명령을 사용하여 명령 행에서 대화식 세션을 기록 할 수 있습니다. 그러나 여기에는 모든 제어 문자 색상 코드가 포함됩니다. "col -b"로 제어 문자 (백 스페이스와 같은)를 제거 할 수 있지만 색상 코드를 제거하는 간단한 방법을 찾을 수 없습니다.

일반적인 방법으로 명령 줄을 사용하고 싶기 때문에 색상을 비활성화하지 않고 스크립트 출력에서 ​​색상을 제거하고 싶습니다. 또한, 나는 놀아서 해결할 수있는 정규 표현식을 찾을 수 있다는 것을 알고 있지만, 더 간단하고 신뢰할 수 있습니다-정규 표현식을 개발할 때 알 수없는 코드가 있다면 무엇입니까?

문제를 보여 주려면 :

spl62 tmp : 스크립트
스크립트가 시작되었습니다. 파일은 typescript입니다
spl62 lepl : ls
add-licence.sed build-example.sh commit-test push-docs.sh
add-licence.sh build.sh delete-licence.sed setup.py
asn build-test.sh delete-licence.sh src
build-doc.sh 깨끗한 doc-src test.ini
spl62 lepl : 종료
스크립트 완료, 파일은 typescript
spl62 tmp : cat -v 타자기
2011 년 6 월 9 일 (목) 09:47:27 AM에 스크립트 시작
spl62 lepl : ls ^ M
^ [[0m ^ [[00madd-licence.sed ^ [[0m ^ [[00; 32mbuild-example.sh ^ [[0m ^ [[00mcommit-test ^ [[0m ^ [[00; 32mpush-docs.sh ^ [[0m ^ M
^ [[00; 32madd-licence.sh ^ [[0m ^ [[00; 32mbuild.sh ^ [[0m ^ [[00mdelete-licence.sed ^] [[0m ^ [[00msetup.py ^ [[0m ^ M
^ [[01; 34masn ^ [[0m ^ [[00; 32mbuild-test.sh ^ [[0m ^ [[00; 32mdelete-licence.sh ^] [[0m ^ [[01; 34msrc ^ [[0m ^ MM))
^ [[00; 32mbuild-doc.sh ^ [[0m ^ [[00; 32mclean ^ [[0m ^ [[01; 34mdoc-src ^ [[0m ^ [[00mtest.ini ^ [[0m ^ M
spl62 파일 : exit ^ M

스크립트 2011 년 6 월 9 일 09:47:29 CLT
spl62 tmp : col -b <유형 스크립트 
2011 년 6 월 9 일 (목) 09:47:27 AM에 스크립트 시작
spl62 lepl : ls
0m00madd-licence.sed0m 00; 32mbuild-example.sh0m 00mcommit-test0m 00; 32mpush-docs.sh0m
00; 32madd-licence.sh0m 00; 32mbuild.sh0m 00m 삭제 -licence.sed0m 00msetup.py0m
01; 34masn0m 00; 32mbuild-test.sh0m 00; 32mdelete-licence.sh0m 01; 34msrc0m
00; 32mbuild-doc.sh0m 00; 32mclean0m 01; 34mdoc-src0m 00mtest.ini0m
spl62 lepl : 종료

스크립트 2011 년 6 월 9 일 09:47:29 CLT

답변:


57

다음 스크립트는 ( ctlseqs 기반)에 대한 모든 ANSI / VT100 / xterm 제어 시퀀스를 필터링해야합니다 . 최소한의 테스트 결과, 일치하지 않거나 초과 한 부분을보고하십시오.

#!/usr/bin/env perl
## uncolor — remove terminal escape sequences such as color changes
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       \e\[ [ -?]* [@-~] | # CSI ... Cmd
       \e\] .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       \e[P^_] .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e. //xg;
    print;
}

알려진 문제 :

  • 잘못된 시퀀스에 대해서는 불평하지 않습니다. 이것이이 스크립트의 목적이 아닙니다.
  • DCS / PM / APC / OSC에 대한 여러 줄 문자열 인수는 지원되지 않습니다.
  • 128–159 범위의 바이트는 제어 문자로 구문 분석 될 수 있지만 거의 사용되지 않습니다. 다음은 비 ASCII 제어 문자를 구문 분석하는 버전입니다 (UTF-8을 포함한 일부 인코딩에서 비 ASCII 텍스트를 엉망으로 만듭니다).
#!/usr/bin/env perl
## uncolor — remove terminal escape sequences such as color changes
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       (?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
       (?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       (?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e.|[\x80-\x9f] //xg;
    print;
}

두 답변 덕분에. 두 가지 모두 정규 표현식을 제공하지만 피하고 싶었지만 좋은 답변으로 뭔가를 만들어야한다고 느꼈습니다. 형식에 대한 참조를 제공하므로 이것을 선택하십시오.
앤드류 쿡

@ andrew : 정규식은 유연성이있어 현재 존재하는 거의 모든 터미널과 내일 존재하는 터미널에서도 작동 할 것으로 기대합니다. 나는 그것을 많이 테스트하지 않았으므로 버그가있을 수 있지만 제어 시퀀스는 몇 가지 일반적인 패턴을 따르므로 접근 방식이 좋습니다.
Gilles

이 스크립트를 사용하는 방법을 알려주십시오. 파이프 입력이 필요합니까? 또는 위치 주장?
Trevor Boyd Smith

@TrevorBoydSmith 어느 쪽이든 입력 작업을 수행하며 일반적인 텍스트 유틸리티와 같이 항상 표준 출력으로 출력됩니다.
Gilles

☺ (\ xe2 \ x98 \ xba)와 같은 멀티 바이트 문자를 맹 글링합니다. [\ x80- \ x9f] 절은 중간 바이트를 제거합니다.
Jeffrey

31

캐리지 리턴을 제거하고 이전 문자의 백 스페이스 지우기를 수행하기 위해 Gilles의 답변을 업데이트했습니다.

#!/usr/bin/perl
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       \r | # Remove extra carriage returns also
       (?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
       (?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       (?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e.|[\x80-\x9f] //xg;
       1 while s/[^\b][\b]//g;  # remove all non-backspace followed by backspace
    print;
}

+1 나는이 메시지를 당신의 스크립트와 @Gilles의 메시지로 좋아할 때 OP와 같은 질문으로 게시물을 이미 입력하고있었습니다. 둘 다 +1
기적 173

10

sed이 경우에 사용하겠습니다 .

하다:

cat -v typescript | sed -e "s/\x1b\[.\{1,5\}m//g"

sed -e "s / search / replace / g"는 표준입니다. 정규식은 다음과 같이 설명됩니다.

\x1b색상 코드 \[.\{1,5\}단일 문자 의 첫 번째 열린 괄호 일치 1 ~ 5와 일치하기 전에 이스케이프를 일치시킵니다 . 할 \을 엉망으로에서 쉘을 유지하기 위해 중괄호. m정규 표현식의 마지막 문자-일반적으로 색상 코드를 추적합니다. //모든 것을 대체 할 빈 문자열. g한 줄에 여러 번 일치시킵니다.


3
이 정규식 스트립 너무 ( foo\e[1m(1m = {해진다 foo = {대신 foo(m = {)로 대체 .함으로써 것이 [0-9;]더 정확하다.
Lekensteyn

교체 .\{1,5\}와 함께 [^m]\{1,5\}그것에 대해 -뿐만 아니라이 그렇다하더라도 여전히 "그래픽 연주"코드 (AN 끝나는 것과 제거주의 m) - 기본적으로 색상, 반전, 굵은 이탤릭체 스타일을 (해당되는 경우).
Hannu

이것은 제거되지 않습니다 \x1b(B(녹 색 출력에 포함됨)
ideasman42

1
\x1b그렇지 \033않습니까?
15 분 21 초에 시작

\u001b대신에 있을 수 있습니다\x1b
yunzen

9
cat typescript | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > typescript-processed

6
# The "sed -r" trick does not work on every Linux, I still dunno why:
DECOLORIZE='eval sed "s,${END}\[[0-9;]*[m|K],,g"'

=> 사용법 :

<commands that type colored output> | ${DECOLORIZE}

테스트 대상 :-AIX 5.x / 6.1 / 7.1-Linux Mandrake / Mandriva / SLES / Fedora-SunOS


3

scriptreplay화면에서 실행 하고 스크롤 백 버퍼를 파일로 덤프 하여 문제를 해결했습니다 .

다음 예상 스크립트가이를 수행합니다.

최대 250.000 줄의 로그 파일을 테스트했습니다. 작업 디렉토리에는 스크립트 로그, "time"이라는 파일과 "1 10"라인에 10.000.000 배의 파일 및 스크립트가 필요합니다. 와 같은 명령 줄 인수로 스크립트 파일의 이름이 필요합니다 ./name_of_script name_of_scriptlog.

#!/usr/bin/expect -f 

set logfile [lindex $argv 0]

if {$logfile == ""} {puts "Usage: ./script_to_readable.exp \$logfile."; exit}

set timestamp [clock format [clock sec] -format %Y-%m-%d,%H:%M:%S]
set pwd [exec pwd]
if {! [file exists ${pwd}/time]} {puts "ERROR: time file not found.\nYou need a file named time with 10.000.000 times the line \"1 10\" in the working directory for this script to work. Please provide it."; exit}
set wc [exec cat ${pwd}/$logfile | wc -l]
set height [ expr "$wc" + "100" ]
system cp $logfile ${logfile}.tmp
system echo $timestamp >> ${logfile}.tmp
set timeout -1
spawn screen -h $height -S $timestamp 
send "scriptreplay -t time -s ${logfile}.tmp 100000 2>/dev/null\r"
expect ${timestamp} 
send "\x01:hardcopy -h readablelog.${timestamp}\r"

send "exit\r"

system sed '/^$/d' readablelog.$timestamp >> readablelog2.$timestamp
system head -n-2 readablelog2.$timestamp >> ${logfile}.readable.$timestamp
system rm -f readablelog.$timestamp readablelog2.$timestamp ${logfile}.tmp

시간 파일은

for i in $(seq 1 10000000); do echo "1 10" >> time; done

시간 파일을 생성하는 명령은 몇 분 동안 100 % CPU 사용을 생성했으며 메모리 사용이 완료된 후 내 메모리 사용은 100 %였으며 명령을 실행하면 "포크 : 메모리를 할당 할 수 없습니다"가 발생했습니다. 그리고 실제로 예상대로 작동하지 않았습니다.
barteks2x 2016 년

타이밍 파일을 생성하는 훨씬 쉬운 방법이 있습니다. 필드는 " delay blocksize"이므로 " "만 만들지 0 <entirefile>않고 지연없이 전체 항목을 덤프 할 이유가 없습니다. 스크립트의 크기에서 첫 번째 줄 ( tail -n +2 typescript|wc -c)을 뺀 다음을 사용하여 타이밍 파일을 만듭니다 echo "0 "`tail -n +2 typescript|wc -c` > timing. 기본적으로 즉각적이며 scriptreplay전체 스크립트를 가장 빠른 속도로 재생합니다.
FeRD

1

동일한 문제에 대한 해결책을 찾는 동안이 질문을 찾았습니다. 조금 더 파고이 링크의 Live Journal 에서이 스크립트를 발견했습니다. 나는 나를 위해 완벽하게 일했다. 또한이 문제와 솔루션 작동 방식에 대해 매우 잘 작성되었습니다. 확실히 읽을만한 가치가 있습니다. http://jdimpson.livejournal.com/7040.html

#!/usr/bin/perl -wp

# clean up control characters and other non-text detritus that shows up 
# when you run the "script" command.

BEGIN {
# xterm titlebar escape sequence
$xtermesc = "\x1b\x5d\x30\x3b";

# the occurence of a backspace event (e.g. cntrl H, cntrol W, or cntrl U)
$backspaceevent = "\x1b\\\x5b\x4b"; # note escaping of third character

# ANSI color escape sequence
$ansiesc = qr/\x1b\[[\d;]*?m/;

# technically, this is arrow-right. For some reason, being used against
# very long backspace jobs. I don't fully understand this, as evidenced
# by the fact that is off by one sometimes.
$bizarrebs = qr/\x1b\[C/;

# used as part of the xterm titlebar mechanism, or when
# a bell sounds, which might happen when you backspace too much.
$bell = "\x07"; # could use \a

$cr = "\x0d"; # could use \r

$backspace = "\x08"; # could use \b
}

s/$xtermesc.+?$bell//g;
s/[$cr$bell]//g;
s/${backspaceevent}//g;
s/$ansiesc//g;
while (s/(.)(?=$backspace)//) { s/$backspace//; } # frickin' sweet 
# For every ^H delete the character immediately left of it, then delete the ^H.
# Perl's RE's aren't R, so I wonder if I could do this in one expression.
while (s/(..)(?=$bizarrebs)//) { s/$bizarrebs//; }

1

특수 도구를 사용하여 스크립트 출력을 일반 텍스트로 변환하는 것이 좋습니다.이 텍스트는 사용자 정의 정규 표현식을 통해 지속적으로 지원되고 잘 테스트됩니다. 그래서 이것은 나를 위해 일했습니다.

$ cat typescript | ansi2txt | col -bp > typescript.txt.bp    
$ cat -v typescript.txt.bp

script 명령은 typescript 파일로 캡처합니다. ansi2txt-컬러 코드, 백 스페이스 등의 이스케이프가있는 ANSI 코드를 일반 텍스트로 변환하지만 부부 이스케이프는 여전히 남아 있습니다. col -bp-완전히 제거했습니다.

최신 Ubuntu 디스코에서 이것을 테스트했으며 작동합니다.


1

우분투 패키지 에는 ansi2txt명령 이 있습니다 colorized-logs. ANSI 색상 코드를 훌륭하게 제거하지만 텍스트를 덮어 쓰기 위해 방출 ^H또는 ^M문자로 생성 된 진행률 막대와 같은 것을 처리하지 않습니다 . col -b해결할 수있는 최선의 결과를 위해 당신이 두 가지를 결합 할 수 있도록,

cat typescript | ansi2txt | col -b

0

터미널에서 cat출력을 보는 데 필요한 모든 것이 사용 되었다는 것을 알았습니다 script. 이것은 또 다른 출력을 파일로 리디렉션 할 때 도움이되지 않습니다,하지만 달리 결과가 읽을 수 있도록 않는 cat -v, col -b또는 텍스트 편집기.

색상을 제거하거나 결과를 파일로 저장하려면 출력을 cat텍스트 편집기 나 다른 cat명령 (예 :

cat > endResult << END
<paste_copied_text_here>
END

1
scriptOP의 경우와 같이 달리기에는 색상 코드가 첨부 된 출력이 포함 되었습니까?
Jeff Schaller

사용 cat은 수동 복사하여 붙여 넣기로 제거 할 수있는 원래 색상을 나타냅니다. OP가 및를 사용 cat -v했으며 col -b둘 다 올바르게 형식화 된 최종 결과가 아닌 코드를 나타냅니다. 내 답변을 편집했습니다.
Roger Dueck

-2

tr과 : cntrl을 사용하는 마지막 대답에 이어 다음과 같이 할 수 있습니다.

sed "/^[[:cntrl:]]/d" output.txt

vi로 생성 된 모든 줄이 제어 문자로 시작하기 때문에 이것은 나를 위해 작동하는 것 같습니다. 빈 줄과 탭으로 시작하는 줄을 제거하지만, 내가하는 일에 효과적입니다. \ n \ m \ t를 제외한 모든 제어 문자를 일치시키는 방법이있을 수 있습니다.

어쩌면 특정 제어 문자를 검색 할 수 있으며, vi에 의해 생성 된 모든 정크 라인은 ^ [와 같은 것으로 시작합니다. hexdump는 첫 번째 문자가 1b라고 알려주므로 작동합니다.

sed "/^\x1b/d" output.txt

이것은 위에 게시 된 답변과 비슷해 보이지만 명령을 실행 한 후 사용자가 입력 한 것처럼 일부 정크 문자가 이미 명령 줄에 추가 되었기 때문에 제대로 작동하지 않습니다.


1
답변이 변경 될 수 있고 변경 순서에 따라 "마지막 답변"이 없습니다. 참조하려는 답변 아래의 "공유"버튼을 사용하여 답변에 링크로 포함시켜야합니다. 당신의 대답은 물론 의견 이상으로 충분하다고 가정하십시오. 현재 귀하가 참조하고있는 몇 가지 답변 중 어떤 것을 식별 할 수 없습니다.
roaima

1
"우리가 어쩌면 ... 할 수있는"예, 우리는 할 수 그렇게 -하지만 것입니다 삭제 모든 라인 시작 제어 문자를 . 예를 들어 ls --color(질문에 표시된 것처럼) 출력 에서 솔루션은 정보가 포함 된 거의 모든 줄을 삭제 합니다. 안좋다. 그러나 쓸모없는 사용을 남겨 주셔서 감사합니다 cat. :-) ⁠
G-Man

: iscntrl :이지만 : isspace :가 아닌 문자 클래스를 작성하는 방법이 있습니까? 어쩌면 ^ [[: iscntrl :] - [: isspace와]] 같은 일부 구문
snaran

-4

tr -번역 또는 문자 삭제

cat typescript | tr -d [[:cntrl:]]

유닉스 스택 교환에 오신 것을 환영합니다! 답을 할 때 왜 답되는지에 대해 설명 하는 것이 좋습니다 .
Stephen Rauch

간결함은 허용되지만 자세한 설명이 더 좋습니다. 또한 여기서 문제를 해결하지 못합니다.
Kusalananda

3
01;34m예를 들어 제거하지 않고 줄 끝을 제거하므로 실제로 올바르게 작동하지 않습니다 newline (\n).
sorontar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.