Kontrol karakterlerini (konsol kodları / renkleri dahil) senaryo çıktısından kaldırma


68

Komut satırında etkileşimli bir oturum kaydetmek için "script" komutunu kullanabilirim. Ancak, bu tüm kontrol karakterlerini ve renk kodlarını içerir. Kontrol karakterlerini (backspace gibi) "col -b" ile kaldırabilirim, ancak renk kodlarını kaldırmak için basit bir yol bulamıyorum.

Komut satırını normal şekilde kullanmak istediğimi, bu yüzden oradaki renkleri devre dışı bırakmak istemediğimi unutmayın - yalnızca komut dosyası çıktısından kaldırmak istiyorum. Ayrıca, etrafta oynayabildiğini ve işleri düzeltmek için bir regexp bulmayı deneyebileceğimi biliyorum, ancak daha basit (ve daha güvenilir - regexp geliştirdiğimde bilmediğim bir kod varsa) çözümünün olacağını umuyorum.

Sorunu göstermek için:

spl62 tmp: komut dosyası
Betik başlatıldı, dosya 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 temiz doc-src test.ini
spl62 lepl: çıkış
Script yapıldı, dosya typescript
spl62 tmp: cat -v typescript
Senaryo başladı Perşembe 09 Haz 2011 09:47:27 CLT
spl62 lepl: ls ^ M
^ [[0m ^ [[00madd-licence.sed ^ [[0m ^ [[00; 32mbuild-example.sh ^ [[0m ^ [[00mbilite testi] ^ [[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: çıkış ^ M

Script Perşembe 10 Haz 2011 09:47:29 CLT tarihinde yapıldı
spl62 tmp: col -b <typescript 
Senaryo başladı Perşembe 09 Haz 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; 34masnmm 00; 32mbuild-test.sh0m 00; 32mdelete-licence.sh0m 01; 34msrc0m
00; 32mbuild-doc.sh0m 00; 32mclean0m 01; 34mdoc-src0m 00mtest.ini0m
spl62 lepl: çıkış

Script Perşembe 10 Haz 2011 09:47:29 CLT tarihinde yapıldı

Yanıtlar:


57

Aşağıdaki komut dosyası ( ctlseq'lara dayanarak ) için tüm ANSI / VT100 / xterm kontrol dizilerini filtrelemelidir . Minimal olarak test edilmiş, lütfen eşleşmeyen veya eşleşmeyenleri bildirin.

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

Bilinen Sorunlar:

  • Yanlış biçimlendirilmiş dizilerden şikayet etmez. Bu senaryo bunun için değil.
  • DCS / PM / APC / OSC'ye çok satırlı dize argümanları desteklenmez.
  • Bu nadir kullanılmasına rağmen, 128-159 aralığındaki baytlar kontrol karakterleri olarak ayrıştırılabilir. İşte ASCII olmayan kontrol karakterlerini ayrıştırılan bir sürüm (UTC-8 de dahil olmak üzere bazı kodlamalarda ASCII olmayan metni yönetir).
#!/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;
}

Her iki cevap için teşekkürler. Her ikisi de önlemek istediğim regexps vermesine rağmen, iyi bir cevap olarak bir şeyler yapmam gerektiğini hissettim. format için referans verirken bunu seçti.
Andrew,

@andrew: Regexp, şu anda var olan herhangi bir terminalle ve muhtemelen de yarın varolan herhangi bir terminalle çalışmasını beklediğim kadar esnek. Çok fazla test etmedim, bu yüzden hatalar olabilir, ancak kontrol sekansları birkaç genel örüntü takip ettikçe yaklaşım sestir.
Gilles,

Lütfen bu betiğin nasıl kullanılacağını sağlayın. boru girişi gerektiriyor mu? veya konumsal argümanlar?
Trevor Boyd Smith

@TrevorBoydSmith Her ikisi de girdi için çalışacak ve çıktı, tipik metin programları gibi her zaman standart çıktıda olacaktır.
Gilles

Bu, ☺ (\ xe2 \ x98 \ xba) gibi çok baytlı karakterleri yönetir. [\ X80- \ x9f] yan tümcesi orta baytı sorar.
Jeffrey

31

Gilles’un cevabını, araba iadelerinin kaldırılması ve Cygwin’de oluşturulan bir yazı tipi için de benim için önemli olan önceki karakterlerin geri silme işleminin yapılması için güncelleniyor:

#!/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 Senaryoyu ve @Gilles'in mesajını okuduğumda OP ile aynı soruyu içeren bir yazı zaten yazıyordum.
İkiniz

10

Ben kullanacağı sedbu durumda.

yap:

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

sed -e "s / search / replace / g" standart malzemedir. regex aşağıda açıklandığı gibidir:

\x1bRenk kodunu önleyen Escape ile eşleşin, \[ilk açık köşeli parantez ile .\{1,5\}eşleştirin, herhangi bir karakterden 1 ile 5 arası. Zorunda \onları bozma gelen kabuk tutmaya küme parantezleri. mregex'deki son karakter - genellikle renk kodunu izler. //her şeyin yerine ne konulacağı için boş dize. gsatır başına birden çok kez eşleştirin.


3
Bu normal ifade şeritler çok ( foo\e[1m(1m = {olur foo = {yerine foo(m = {), yerine .göre [0-9;]daha doğrudur.
Lekensteyn

Değiştir .\{1,5\}ile [^m]\{1,5\}bunun için - ama aynı zamanda bu zaman bile hala sadece "grafik teslimat" kodları (bir sona olanlar kaldırır unutmayın m) - temelde renk, ters, kalın ve italik stilleri (varsa).
Hannu

Bu kaldırmaz \x1b(B(rusts renk çıkışında bulunur)
ideasman42

1
Neden öyle \x1bdeğil \033?
atripes,

Bunun \u001byerine olabilir\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"'

=> nasıl kullanılır:

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

test edildi: - AIX 5.x / 6.1 / 7.1 - Linux Mandrake / Mandriva / SLES / Fedora - SunOS


3

scriptreplayBir ekranda çalıştırarak ve kaydırma arabelleğini bir dosyaya atarak sorunu çözdüm.

Aşağıdaki bekleyiş komut dosyası sizin için yapar.

250.000 satıra kadar logfile için test edilmiştir. Çalışma dizininde scriptlog, "time" adlı bir dosyada 10.000.000 kat "10" satırına sahip bir dosyaya ve komut dosyasına ihtiyacınız var. Senaryo dosyanızın ismine, komut satırı argümanı gibi ihtiyacım var ./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

Zaman dosyası tarafından oluşturulabilir.

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

Zaman dosyası oluşturma komutu birkaç dakika boyunca% 100 CPU kullanımı sağladı ve tamamladıktan sonra hafıza kullanımı% 100'dü ve çalıştırma komutu "fork: bellek ayıramıyor" ile sonuçlandı. Ve beklendiği gibi gerçekten işe yaramadı.
barteks2x

Zamanlama dosyasını oluşturmanın çok daha kolay bir yolu var. Alanlar " delay blocksize", bu yüzden sadece " 0 <entirefile>" yapmamak için hiçbir sebep yok ve her şeyi gecikmeden atıyorlar. Bunu komut dosyasının boyutunu eksi ilk satırı ( tail -n +2 typescript|wc -c) alarak yapabilir ve zamanlama dosyasını birlikte oluşturabilirsiniz echo "0 "`tail -n +2 typescript|wc -c` > timing. Bu temelde anlık scriptreplayolacak ve betiğin tamamını mümkün olan en hızlı şekilde tekrarlayacaktır.
FeRD

1

Aynı soruna bir çözüm ararken bu soruyu buldum. Biraz daha kazıyor ve bu yazıyı bu linkte Live Journal'da buldum. Benim için mükemmel çalıştım. Aynı zamanda bu sorun ve çözümün nasıl çalıştığı hakkında çok iyi bir yazı. Kesinlikle bir okumaya değer. 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

Özel regexp üzerinden komut dosyası çıktısını sürekli olarak desteklenen ve iyi test edilen düz metne dönüştürmek için özel araçlar kullanmayı tercih ederim. Yani bu benim için iş yaptı:

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

script komutu, ansi2txt yazarken, ansi2txt - renk kodları, backspaces, vb. col -bp - tamamen kaldırıldı.

Bunu en son Ubuntu diskoda test ettim ve işe yarıyor.


1

Ubuntu'daki pakette bir ansi2txtkomut var colorized-logs. ANSI renk kodlarını güzel bir şekilde kaldırır, ancak yayma tarafından üretilen ilerleme çubukları ^Hveya ^Myerdeki metnin üzerine yazmak için kullanılan karakterlerle ilgili değildir. bunlarlacol -b başa çıkabilir , böylece en iyi sonuçları elde etmek için ikisini birleştirebilirsiniz.

cat typescript | ansi2txt | col -b

0

Sadece kullanmanın terminaldeki catçıktısını görüntülemek için gereken tek şey olduğunu buldum script. Bu, başka bir dosyaya çıktı yönlendirme yaparken yardımcı olmuyor, ama aksine, sonuç okunabilir hale gelmez cat -v, col -bya da bir metin editörü.

Renkleri ortadan kaldırmak veya sonuçları bir dosyaya kaydetmek için, çıktıyı catbir metin düzenleyiciye veya başka bir catkomuta el ile kopyalayıp yapıştırın , örn:

cat > endResult << END
<paste_copied_text_here>
END

1
OP'nizde scriptolduğu gibi koşunuzda renk kodları eklenmiş çıktılar içeriyor mu?
Jeff Schaller

Kullanarak cat, elle kopyala ve yapıştır ile kaldırılabilen orijinal renkler sunulur. OP , her ikisi de düzgün biçimlendirilmiş bir sonuçtan ziyade kodları içeren cat -vve kullanılmış col -b. Cevabımı düzenledim.
Roger Dueck

-2

Tr ve cntrl'yi kullanan son cevabı takip etmek: belki yapabilir miyiz

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

Bu benim için çalışıyor gibi görünüyor, çünkü vi tarafından üretilen tüm satırlar kontrol karakteriyle başlar. Ayrıca, yaptığım işe yaramasına rağmen, bir sekme ile başlayan boş satırları ve satırları da çıkarır. Belki de \ n \ m \ t dışında herhangi bir kontrol karakteriyle eşleşmenin bir yolu vardır.

Belki belirli bir kontrol karakterini arayabiliriz, ve vi tarafından oluşturulan tüm önemsiz satırlara benziyor ^. hexdump bana ilk karakterin 1b olduğunu söyledi, bu yüzden bu da işe yarıyor

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

Bu, yukarıda verilen cevaplara benzer, ancak düzgün çalışmaz, çünkü komutu çalıştırdıktan sonra, bazı önemsiz karakterler zaten kullanıcı yazmış gibi komut satırına eklenir.


1
Cevaplar sırasını değiştirebildiği ve değiştirebildiği için "son cevap" yoktur. Başvurmak istediğiniz cevabın altındaki "paylaş" düğmesini kullanmanız ve cevabınıza bir bağlantı olarak eklemeniz gerekir. Cevabınızın, bir yorumdan daha fazlası olması için yeterli olduğu varsayılmaktadır. Şu anda hangi yanıttan bahsettiğinizi tanımlayamıyorum.
roaima

1
“Biz belki ... yapabileceğini” Evet, olabilir bunu - ama olur silmek her satırını başlar bir kontrol karakteri ile . Örneğin ls --color(soruda gösterildiği gibi) çıktısında, çözümünüz bilgi içeren hemen hemen her satırı siler . İyi değil. Ama işe yaramaz kullanımı dışında bıraktığın için teşekkürler cat. :-) ⁠
G-Man

Karakter sınıfı oluşturmanın bir yolu var mı: iscntrl: ama değil: isspace :? Belki bazı sözdizimi ^ [[: iscntrl:] - [: isspace]]
snaran

-4

tr - karakterleri çevir veya sil

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

Unix Stackexchange'e Hoş Geldiniz! Bir cevap verirken, cevabınızın NEDEN olduğu konusunda bir açıklama yapmanız tercih edilir .
Stephen Rauch


3
Bu aslında, 01;34mörneğin bir örneği kaldırmayacağından ve satır sonunu kaldıracağından doğru çalışmayacaktır newline (\n).
sorontar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.