Menghapus kode warna ANSI dari aliran teks

73

Memeriksa output dari

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";'

dalam editor teks (misalnya, vi) menunjukkan yang berikut:

^[[37mABC
^[[0m

Bagaimana cara menghapus kode warna ANSI dari file output? Saya kira cara terbaik adalah menyalurkan output melalui semacam editor aliran.

Berikut ini tidak berfungsi

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' | perl -pe 's/\^\[\[37m//g' | perl -pe 's/\^\[\[0m//g'
user001
sumber
Bukan jawaban untuk pertanyaan itu, tetapi Anda juga dapat menyalurkan output ke moreatau less -Ryang dapat menafsirkan kode pelarian sebagai warna, bukan editor teks.
terdon

Jawaban:

98

Karakter ^[[37mdan ^[[0mmerupakan bagian dari urutan pelarian ANSI (kode CSI) . Lihat juga spesifikasi ini .

Menggunakan GNU sed

sed 's/\x1b\[[0-9;]*m//g'
  • \x1b(atau \x1B) adalah karakter spesial pelarian
    ( sedtidak mendukung alternatif \edan \033)
  • \[ adalah karakter kedua dari urutan pelarian
  • [0-9;]* adalah nilai warna regex
  • m adalah karakter terakhir dari urutan pelarian

⚠ Pada macOS, sedperintah default tidak mendukung karakter khusus seperti yang \editunjukkan oleh slm dan steamer25 di komentar. Gunakan sebaliknya gsedyang dapat Anda instal menggunakan brew install gnu-sed.

Contoh dengan baris perintah OP :   (OP berarti Poster Asli)

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' | 
      sed 's/\x1b\[[0-9;]*m//g'

Tom Hale menyarankan untuk menghapus semua urutan pelarian lainnya dengan menggunakan [a-zA-Z]alih-alih hanya huruf yang mspesifik untuk urutan melarikan diri mode grafis (warna). Tetapi [a-zA-Z]mungkin terlalu lebar dan bisa menghapus terlalu banyak. Michał Faleński dan Miguel Mota mengusulkan untuk menghapus hanya beberapa urutan melarikan diri menggunakan [mGKH]dan [mGKF]masing - masing. Britton Kerin menunjukkan Kjuga harus digunakan selain muntuk menghapus warna dari gcckesalahan / peringatan (jangan lupa untuk mengarahkan ulang gcc 2>&1 | sed...).

sed 's/\x1b\[[0-9;]*m//g'           # Remove color sequences only
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g'    # Remove all escape sequences
sed 's/\x1b\[[0-9;]*[mGKH]//g'      # Remove color and move sequences
sed 's/\x1b\[[0-9;]*[mGKF]//g'      # Remove color and move sequences
Last escape
sequence
character   Purpose
---------   -------------------------------
m           Graphics Rendition Mode (including Color)
G           Horizontal cursor move
K           Horizontal deletion
H           New cursor position
F           Move cursor to previous n lines

Menggunakan perl

Versi yang seddiinstal pada beberapa sistem operasi mungkin terbatas (mis. MacOS). Perintah ini perlmemiliki keuntungan karena secara umum lebih mudah untuk menginstal / memperbarui pada lebih banyak sistem operasi. Adam Katz menyarankan untuk menggunakan \e(sama seperti \x1b) di PCRE .

Pilih regex Anda tergantung pada seberapa banyak perintah yang ingin Anda filter:

perl -pe 's/\e\[[0-9;]*m//g'          # Remove colors only
perl -pe 's/\e\[[0-9;]*[mG]//g'
perl -pe 's/\e\[[0-9;]*[mGKH]//g'
perl -pe 's/\e\[[0-9;]*[a-zA-Z]//g'
perl -pe 's/\e\[[0-9;]*m(?:\e\[K)?//g' # Adam Katz's trick

Contoh dengan baris perintah OP:

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' \
      | perl -pe 's/\e\[[0-9;]*m//g'

Pemakaian

Seperti yang ditunjukkan oleh komentar Stuart Cardall , sedbaris perintah ini digunakan oleh proyek Ultimate Nginx Bad Bot (1000 bintang) untuk membersihkan laporan email ;-)

olibre
sumber
2
Terima kasih untuk sedperintah dan penjelasannya. :)
Redsandro
2
Beberapa kode warna (misalnya terminal Linux) berisi awalan, mis. 1;31mJadi lebih baik tambahkan ;ke regex Anda: cat colored.log | sed -r 's/\x1b\[[0-9;]*m//g'atau tidak akan dilucuti.
Redsandro
1
ini bagus digunakan di github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/blob/… untuk membersihkan laporan email.
Stuart Cardall
2
Perlu diingat bahwa versi OSX sedtidak berfungsi dengan contoh yang diperlihatkan, gsednamun versi tersebut tidak.
slm
2
Lebih banyak konteks untuk komentar slm tentang OSX sed: ia tidak mendukung karakter kontrol seperti \ x1b. Misalnya, stackoverflow.com/a/14881851/93345 . Anda bisa mendapatkan perintah gsed melalui brew install gnu-sed.
steamer25
21

Saya telah menemukan penghilang urutan pelarian yang lebih baik. Periksa ini:

perl -pe 's/\x1b\[[0-9;]*[mG]//g'

pengguna204331
sumber
2
Apa peningkatan dari jawaban yang diterima ( superuser.com/a/380778/46794 )?
Blaisorblade
4
@ Blaisorblade Ini berfungsi pada OS X, sedangkan sed -rTIDAK.
BVengerov
10

Apa yang ditampilkan sebagai ^[yang tidak ^ dan [; itu adalah ESCkarakter ASCII , diproduksi oleh Escatau Ctrl[( ^notasi berarti kunci Ctrl).

ESCadalah 0x1B heksadesimal atau 033 oktal, jadi Anda harus menggunakan \x1Batau \033di regex Anda:

perl -pe 's/\033\[37m//g; s/\033[0m//g'

perl -pe 's/\033\[\d*(;\d*)*m//g'
grawity
sumber
6

Jika Anda lebih suka sesuatu yang sederhana, Anda bisa menggunakan modul strip-ansi ( diperlukan Node.js ):

$ npm install --global strip-ansi-cli

Kemudian gunakan seperti ini:

$ strip-ansi < colors.o

Atau cukup masukkan string:

$ strip-ansi '^[[37mABC^[[0m'
Sindre Sorhus
sumber
Ini penggunaan tidak berguna cat( UUOC ) - itu harus mungkin dilakukan strip-ansi colors.oatau setidaknya strip-ansi < colors.o.
Scott
1
@ Esc Yakin, Anda juga bisa melakukannya strip-ansi < colors.o, tetapi dari pengalaman orang lebih akrab dengan perpipaan. Saya sudah memperbarui jawabannya.
Sindre Sorhus
solusi sederhana yang bagus
Penghe Geng
3

Saya percaya ini adalah penghapusan semua urutan melarikan diri ANSI :

perl -pe '
  s/\e\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]//g;
  s/\e[PX^_].*?\e\\//g;
  s/\e\][^\a]*(?:\a|\e\\)//g;
  s/\e[\[\]A-Z\\^_@]//g;'

(Harap dicatat bahwa perl, seperti banyak bahasa lain (tetapi tidak sed), menerima \esebagai karakter pelarian Esc, \x1batau \033dengan kode, ditunjukkan dalam terminal sebagai ^[. Saya menggunakannya di sini karena tampaknya lebih intuitif.)

Perintah perl ini, yang bisa Anda jalankan semua dalam satu baris jika Anda mau, memiliki empat penggantian di dalamnya:

Yang pertama setelah sekuens CSI (urutan kode escape yang dimulai dengan "Control Sequence Introducer" of Esc[, yang mencakup lebih banyak daripada sekuens Select Graphic Rendition yang membentuk kode warna dan dekorasi teks lainnya).

Penggantian kedua menghapus urutan yang tersisa yang melibatkan karakter tambahan dan diakhiri dengan ST (Terminator String, Esc\). Penggantian ketiga adalah hal yang sama tetapi juga memungkinkan Sistem Operasi Command urutan untuk mengakhiri dengan BEL ( \x07, \007, sering \a).

Penggantian keempat menghilangkan sisa yang tersisa.

Juga pertimbangkan untuk menghapus karakter ASCII dengan lebar nol lainnya seperti BEL dan karakter kontrol C0 dan C1 lainnya yang tidak jelas . Saya telah menggunakan s/[\x00-\x1f\x7f-\x9f\xad]+//g, yang juga termasuk Hapus dan Tanda Hubung Lunak . Ini tidak termasuk karakter nol-lebar berkode lebih tinggi dari Unicode, tetapi saya percaya ini lengkap untuk ASCII (Unicode \x00- \xff). Jika Anda melakukan ini, hapus yang terakhir karena mereka dapat terlibat dalam urutan yang lebih panjang.

Adam Katz
sumber
2

Pertanyaan "dijawab" tidak berhasil untuk saya, jadi saya membuat regex ini sebagai gantinya untuk menghapus urutan pelepasan yang dihasilkan oleh perl Term :: ANSIColor module.

cat colors.o | perl -pe 's/\x1b\[[^m]+m//g;

Regex Grawity seharusnya bekerja dengan baik, tetapi menggunakan + tampaknya juga berfungsi.

castl3bravo
sumber
4
(1) Apa maksudmu The "answered" question? Apakah maksud Anda jawaban yang diterima? (2) Perintah ini tidak berfungsi - bahkan tidak mengeksekusi - karena ia memiliki kutipan yang tidak cocok (tidak seimbang). (3) Ini penggunaan yang tidak berguna cat( UUOC ) - itu harus mungkin dilakukan . (4) Siapa yang pernah mengatakan sesuatu tentang kode yang ada dalam file? perl -pe command colors.o.o
Scott
1

"tput sgr0" meninggalkan karakter kontrol ini ^ (B ^ [
Ini adalah versi yang dimodifikasi untuk mengatasi hal itu.

perl -pe 's/\e[\[\(][0-9;]*[mGKFB]//g' logfile.log
GustafAnkarloo
sumber
Terima kasih untuk ini ... ini berhasil bagi saya untuk menyingkirkan itu tput sgr0bahwa solusi lain sepertinya tidak pernah bisa dihilangkan.
TxAG98
0

Saya memiliki masalah yang sama dengan menghapus karakter yang ditambahkan dari mengumpulkan output top interaktif melalui dempul dan ini membantu:

cat putty1.log | perl -pe 's/\x1b.*?[mGKH]//g'
Michał Faleński
sumber
3
Ini penggunaan yang tidak berguna cat( UUOC ) - itu harus mungkin dilakukan . perl -pe command putty1.log
Scott
0

Inilah yang bekerja untuk saya (diuji pada Mac OS X)

perl -pe 's/\[[0-9;]*[mGKF]//g'
Miguel Mota
sumber