web-dev-qa-db-ja.com

スクリプト出力からの制御文字(コンソールコード/色を含む)の削除

「script」コマンドを使用して、コマンドラインでインタラクティブセッションを記録できます。ただし、これにはすべての制御文字andカラーコードが含まれます。 「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 clean doc-src test.ini 
 spl62 lepl:exit 
 Script done、file is TypeScript 
 spl62 tmp:cat -v TypeScript 
スクリプトは6月9日(木)に開始されました2011 09:47:27 AM CLT 
 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 ^ M 
 ^ [[00; 32mbuild-doc.sh ^ [[0m ^ [[00; 32mclean ^ [[0m ^ [[01; 34mdoc-src ^ [[0m ^ [[00mtest.ini ^ [[0m ^ M 
 spl62 lepl:exit ^ M 
 
スクリプトは木曜日09に完了しました2011年6月09:47:29 AM CLT 
 spl62 tmp:col -b <TypeScript 
スクリプトは木曜日09に開始2011年6月09:47:27 AM CLT 
 spl62 lepl:ls 
 0m00madd-licence.sed0m 00; 32mbuild-example.sh0m 00mcommit-test0m 00; 32mpush-docs.sh0m 
 00; 32madd-licence.sh0m 00; 32mbuild.sh0m 00mdelete-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:exit 
 
スクリプトは2011年6月9日木曜日09:47:29 AM CLTに作成されました
71
andrew cooke

次のスクリプトは、( 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;
}

Gillesの回答を更新して、キャリッジリターンを削除し、以前の文字をバックスペースで消去します。これらは、Cygwinで生成されたTypeScriptで私にとって重要でした。

#!/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;
}
31
dewtell

この場合、sedを使用します。

行う:

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

sed -e "s/search/replace/g"は標準的なものです。正規表現は次のように説明されます:

\x1bは、カラーコードの前のエスケープに一致します\[は、最初の開き角括弧に一致します.\{1,5\}は、任意の1文字の1〜5に一致します。シェルがそれらを混乱させないようにするには、中括弧を\する必要があります。 m正規表現の最後の文字-通常、カラーコードの後に​​続きます。 //すべてを何に置き換えるかを表す空の文字列。 g行ごとに複数回一致します。

12
Glorytoad
cat TypeScript | Perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > TypeScript-processed
9
Peter Nore
# 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

6
scavenger

Ubuntuのansi2txtパッケージには colorized-logs コマンドがあります。 ANSIカラーコードは適切に削除されますが、^Hまたは^M文字を発行してテキストを上書きすることで生成されるプログレスバーなどは処理されません。 col -bこれらを処理できるため、最良の結果を得るには2つを組み合わせることができます

cat TypeScript | ansi2txt | col -b
5
Marius Gedminas

画面でscriptreplayを実行し、スクロールバックバッファーをファイルにダンプすることで問題を解決しました。

次のexpectスクリプトはこれを行います。

最大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
3
hnkchnsk

スクリプト出力をプレーンテキストに変換するために、カスタム正規表現よりも常にサポートされ、十分にテストされている専用ツールを使用したいと思います。だからこれは私のために仕事をしました:

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

スクリプトコマンドはTypeScriptファイルansi2txtにキャプチャします-カラーコード、バックスペースなどのエスケープ付きのANSIコードを通常のテキストに変換しますが、いくつかのエスケープがまだ残っていることがわかりました。 col -bp-それらを完全に削除しました。

私はこれを最新のUbuntuディスコでテストしましたが、動作します。

1
Dmytro Brazhnyk

catを使用するだけで、ターミナルでscriptの出力を表示できます。これは、出力を別のファイルにリダイレクトする場合には役立ちませんが、cat -vcol -b、またはテキストエディターとは異なり、結果を読みやすくします。

色を削除するか、結果をファイルに保存するには、catからの出力を手動でコピーしてテキストエディターまたは別のcatコマンドに貼り付けます。

cat > endResult << END
<paste_copied_text_here>
END
1
Roger Dueck

同じ問題の解決策を探しているときにこの質問を見つけました。もう少し掘り下げて、このリンクの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
SammerV

これまでの解決策は制御シーケンスを削除するためにうまく機能しますが、フォーマットコードも削除します。その結果、出力のテーブルがまとめて圧縮されます。私の要件は、ターミナルから収集されたセッションログファイルを表示および検索できることだけでした。私にとって最も効果的な解決策は、少ない-rを使用することでした。

less -r session.log
0
AliA