Menghapus karakter kontrol (termasuk kode / warna konsol) dari output skrip


68

Saya dapat menggunakan perintah "skrip" untuk merekam sesi interaktif di baris perintah. Namun, ini termasuk semua karakter kontrol dan kode warna. Saya dapat menghapus karakter kontrol (seperti backspace) dengan "col -b", tetapi saya tidak dapat menemukan cara sederhana untuk menghapus kode warna.

Perhatikan bahwa saya ingin menggunakan baris perintah dengan cara biasa, jadi jangan ingin menonaktifkan warna di sana - Saya hanya ingin menghapusnya dari output skrip. Juga, saya tahu bisa bermain-main dan mencoba menemukan regexp untuk memperbaiki, tetapi saya berharap ada yang lebih sederhana (dan lebih dapat diandalkan - bagaimana jika ada kode yang saya tidak tahu ketika saya mengembangkan solusi regexp?).

Untuk menunjukkan masalah:

spl62 tmp: skrip
Script dimulai, file adalah naskah
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: keluar
Script selesai, file adalah naskah
spl62 tmp: skrip kucing -v
Script dimulai pada Kamis 09 Jun 2011 09:47:27 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: keluar ^ M

Script dilakukan pada Kamis 09 Jun 2011 09:47:29 CLT
spl62 tmp: col -b <naskah naskah 
Script dimulai pada Kamis 09 Jun 2011 09:47:27 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: keluar

Script dilakukan pada Kamis 09 Jun 2011 09:47:29 CLT

Jawaban:


57

Skrip berikut harus memfilter semua urutan kontrol ANSI / VT100 / xterm untuk (berdasarkan ctlseqs ). Diuji secara minimal, tolong laporkan ada yang kurang atau lebih cocok.

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

Masalah Dikenal:

  • Tidak mengeluh tentang urutan yang salah. Bukan untuk apa skrip ini dibuat.
  • Argumen string multi-baris ke DCS / PM / APC / OSC tidak didukung.
  • Bytes dalam kisaran 128–159 dapat diuraikan sebagai karakter kontrol, meskipun ini jarang digunakan. Berikut adalah versi yang mem-parsing karakter kontrol non-ASCII (ini akan memotong-motong teks non-ASCII dalam beberapa penyandian termasuk UTF-8).
#!/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;
}

terima kasih untuk kedua jawaban. Saya merasa saya harus membuat sesuatu sebagai jawaban yang baik, meskipun keduanya memberikan regexps, yang ingin saya hindari. pilih yang ini karena memberikan referensi untuk format.
andrew cooke

@andrew: Regexp saya cukup fleksibel sehingga saya berharap bisa bekerja dengan hampir semua terminal yang ada sekarang, dan mungkin dengan terminal yang ada besok juga. Saya belum banyak mengujinya, jadi mungkin ada bug, tetapi pendekatannya masuk akal karena urutan kontrol mengikuti beberapa pola umum.
Gilles 'SO- berhenti menjadi jahat'

tolong berikan cara menggunakan skrip ini. apakah itu membutuhkan input pipa? atau argumen posisi?
Trevor Boyd Smith

@TrevorBoydSmith Entah akan bekerja untuk input, dan output selalu pada output standar, seperti utilitas teks biasa.
Gilles 'SANGAT berhenti menjadi jahat'

Ini membuat karakter multibyte seperti ☺ (\ xe2 \ x98 \ xba). Klausa [\ x80- \ x9f] menghapus byte tengah.
Jeffrey

31

Memperbarui jawaban Gilles untuk juga menghapus carriage returns dan melakukan backspace-delete karakter sebelumnya, yang keduanya penting bagi saya untuk naskah yang dihasilkan di Cygwin:

#!/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 Saya sudah mengetik posting dengan pertanyaan yang sama dengan OP ketika saya menyukai pesan ini dengan skrip Anda dan @Gilles. +1 untuk Anda berdua
miracle173

10

Saya akan menggunakan seddalam kasus ini.

melakukan:

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

sed -e "s / search / replace / g" adalah hal standar. regex dijelaskan sebagai berikut:

\x1bcocok dengan Escape sebelum kode warna \[cocok dengan braket terbuka pertama .\{1,5\}cocok dengan 1 hingga 5 karakter tunggal. Harus \kurung kurawal untuk menjaga cangkang dari mangling mereka. mkarakter terakhir di regex - biasanya mengikuti kode warna. //string kosong untuk apa mengganti segalanya. gcocokkan beberapa kali per baris.


3
Strip regex ini terlalu banyak ( foo\e[1m(1m = {menjadi foo = {bukan foo(m = {), menggantikan .dengan [0-9;]lebih akurat.
Lekensteyn

Ganti .\{1,5\}dengan [^m]\{1,5\}untuk itu - tetapi juga perhatikan bahwa ini masih hanya menghapus kode "rendisi grafis" (yang berakhiran dengan m) - pada dasarnya warna, terbalik, tebal dan miring (jika ada).
Hannu

Ini tidak menghapus \x1b(B(termasuk dalam keluaran warna karat)
ideasman42

1
Kenapa begitu \x1bdan tidak \033?
Atrip

Mungkin \u001bbukan\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"'

=> Bagaimana cara menggunakan:

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

diuji pada: - AIX 5.x / 6.1 / 7.1 - Linux Mandrake / Mandriva / SLES / Fedora - SunOS


3

Saya memecahkan masalah dengan menjalankan scriptreplaydi layar dan membuang buffer scrollback ke file.

Skrip harapan berikut melakukan ini untuk Anda.

Ini telah diuji untuk file log dengan hingga 250.000 baris. Di direktori kerja Anda memerlukan skrip, file bernama "waktu" dengan 10.000.000 kali baris "1 10" di dalamnya, dan skrip. Saya membutuhkan nama scriptfile Anda sebagai argumen baris perintah, seperti ./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

File waktu dapat dibuat oleh

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

Perintah untuk menghasilkan file waktu menghasilkan penggunaan CPU 100% selama beberapa menit dan setelah selesai penggunaan memori saya adalah 100% dan menjalankan perintah menghasilkan "garpu: tidak dapat mengalokasikan memori". Dan itu tidak benar-benar berfungsi seperti yang diharapkan.
barteks2x

Ada cara yang jauh lebih mudah untuk menghasilkan file timing. Kolomnya " delay blocksize", jadi tidak ada alasan untuk tidak membuatnya " 0 <entirefile>" dan membuang semuanya tanpa penundaan. Anda dapat melakukannya dengan mengambil ukuran skrip minus baris pertama ( tail -n +2 typescript|wc -c), dan membuat file timing dengan echo "0 "`tail -n +2 typescript|wc -c` > timing. Itu pada dasarnya akan instan, dan scriptreplayakan memutar ulang seluruh skrip dengan kecepatan secepat mungkin.
FeRD

1

Menemukan pertanyaan ini sambil mencari solusi untuk masalah yang sama. Sedikit lagi menggali dan menemukan skrip ini di Live Journal di tautan ini. Saya bekerja dengan sempurna untuk saya. Ini juga merupakan tulisan yang sangat bagus tentang masalah ini dan bagaimana solusinya bekerja. Pasti layak dibaca. 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

Saya lebih suka menggunakan alat khusus untuk mengubah output skrip menjadi teks biasa, yang secara konstan didukung dan diuji dengan baik, melalui custom regexp. Jadi ini berhasil bagi saya:

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

perintah skrip menangkap ke dalam file skrip ansi2txt - mengubah kode ansi dengan lolos seperti colorcodes, backspaces dll menjadi teks biasa, namun saya menemukan bahwa beberapa lolos masih tersisa. col -bp - menghapusnya sepenuhnya.

Saya sudah menguji ini pada disko Ubuntu terbaru, dan itu berhasil.


1

Ada ansi2txtperintah dalam colorized-logspaket di Ubuntu. Ini menghapus kode warna ANSI dengan baik, tetapi tidak menangani hal-hal seperti progress bar yang dihasilkan oleh emitting ^Hatau ^Mkarakter untuk menimpa teks pada tempatnya. col -bdapat menangani mereka , sehingga untuk hasil terbaik Anda bisa menggabungkan dua

cat typescript | ansi2txt | col -b

0

Saya menemukan bahwa hanya menggunakan catitu yang saya butuhkan untuk melihat output scriptdi terminal. Ini tidak membantu ketika mengarahkan output ke file lain, tetapi tidak membuat hasilnya dibaca, tidak seperti cat -v, col -batau editor teks.

Untuk menghilangkan warna atau menyimpan hasil ke file, salin dan tempel output secara manual dari catke editor teks, atau ke catperintah lain , yaitu:

cat > endResult << END
<paste_copied_text_here>
END

1
apakah proses Anda scriptmenyertakan output dengan kode warna terlampir, seperti dalam kasus OP?
Jeff Schaller

Menggunakan cathadiah warna asli, yang dapat dihapus dengan cara salin dan tempel manual. OP menggunakan cat -vdan col -b, keduanya menampilkan kode alih-alih hasil akhir yang diformat dengan benar. Saya telah mengedit jawaban saya.
Roger Dueck

-2

Menindaklanjuti jawaban terakhir yang menggunakan tr dan: cntrl: mungkin bisa kita lakukan

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

Ini sepertinya bekerja untuk saya karena semua baris yang dihasilkan oleh vi mulai dengan karakter kontrol. Kebetulan juga menghapus garis kosong dan garis yang dimulai dengan tab, meskipun itu bekerja untuk apa yang saya lakukan. Mungkin ada cara untuk mencocokkan karakter kontrol apa pun kecuali \ n \ m \ t.

Mungkin kita dapat mencari karakter kontrol tertentu, dan sepertinya semua baris sampah yang dihasilkan oleh vi mulai dengan apa yang tampak seperti ^ [. hexdump memberitahu saya karakter pertama adalah 1b, jadi ini sepertinya berhasil juga

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

Ini terlihat mirip dengan jawaban yang diposting di atas, tetapi tidak berfungsi dengan baik karena setelah menjalankan perintah, beberapa junk chars sudah ditambahkan ke baris perintah seolah-olah pengguna telah mengetiknya.


1
Tidak ada "jawaban terakhir" karena jawaban dapat dan memang mengubah urutan. Anda harus menggunakan tombol "bagikan" di bawah jawaban yang ingin Anda rujuk, dan sertakan itu sebagai tautan dalam jawaban Anda. Anggap jawaban Anda cukup untuk lebih dari sekadar komentar, tentu saja. Saat ini saya tidak dapat mengidentifikasi mana dari beberapa jawaban yang Anda referensikan.
roaima

1
"Bisakah kita melakukan ..." Ya, kita bisa melakukan itu - tetapi itu akan menghapus setiap baris yang dimulai dengan karakter kontrol . Pada output, misalnya, ls --color(seperti yang ditunjukkan dalam pertanyaan), solusi Anda akan menghapus hampir setiap baris yang berisi informasi. Tidak baik. Tapi terima kasih telah meninggalkan penggunaan yang tidak berguna cat. :-) ⁠
G-Man

Apakah ada cara untuk membuat kelas karakter yaitu: iscntrl: tetapi tidak: isspace :? Mungkin beberapa sintaks seperti ^ [[: iscntrl:] - [: isspace]]
snaran

-4

tr - menerjemahkan atau menghapus karakter

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

Selamat Datang di Unix Stackexchange! Saat memberikan jawaban, lebih baik memberi penjelasan mengapa MENGAPA jawaban Anda adalah jawabannya .
Stephen Rauch


3
Ini sebenarnya tidak akan berfungsi dengan benar, karena tidak akan menghapus 01;34mmisalnya, dan akan menghapus akhir baris newline (\n).
sorontar
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.