การลบ chars ควบคุม (รวมถึงรหัสคอนโซล / สี) ออกจากสคริปต์


68

ฉันสามารถใช้คำสั่ง "สคริปต์" เพื่อบันทึกเซสชันแบบโต้ตอบที่บรรทัดคำสั่ง อย่างไรก็ตามสิ่งนี้รวมถึงตัวควบคุมและรหัสสีทั้งหมด ฉันสามารถลบอักขระควบคุม (เช่น backspace) ด้วย "col -b" แต่ฉันไม่พบวิธีที่ง่ายในการลบรหัสสี

โปรดทราบว่าฉันต้องการใช้บรรทัดคำสั่งในวิธีปกติดังนั้นไม่ต้องการปิดการใช้งานสีที่นั่น - ฉันแค่ต้องการลบพวกเขาออกจากสคริปต์ออก นอกจากนี้ฉันรู้ว่าสามารถเล่นและลองค้นหา regexp เพื่อแก้ไขสิ่งต่าง ๆ แต่ฉันหวังว่าจะมีวิธีที่ง่ายกว่า (และเชื่อถือได้มากกว่า - จะเกิดอะไรขึ้นถ้ามีรหัสที่ฉันไม่รู้เมื่อฉันพัฒนา regexp)

ในการแสดงปัญหา:

spl62 tmp: script
สคริปต์เริ่มทำงานแล้วไฟล์คือ 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
สคริปต์เสร็จแล้วไฟล์คือ typescript
spl62 tmp: cat -v typescript
สคริปต์เริ่มเมื่อวันที่ 09 มิ.ย. 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 ^ [[0m ^ M [0m ^ M]
^ [[00; 32mbuild-doc.sh ^ [[0m ^ [[00; 32mclean ^] [0m ^ [[01; 34mdoc-src ^ [[0m ^ [[00mtest.ini ^] [[0m ^ M
spl62 lepl: exit ^ M

สคริปต์เสร็จสิ้นในวันพฤหัสบดีที่ 9 มิ.ย. 2011 เวลา 09:47:29 น. CLT
spl62 tmp: col -b <typescript 
สคริปต์เริ่มเมื่อวันที่ 09 มิ.ย. 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: exit

สคริปต์เสร็จสิ้นในวันพฤหัสบดีที่ 9 มิ.ย. 2011 เวลา 09:47:29 น. CLT

คำตอบ:


57

สคริปต์ต่อไปนี้ควรกรองลำดับการควบคุม ANSI / VT100 / xterm ทั้งหมดสำหรับ (ตามctlseqs ) ทดสอบน้อยที่สุดโปรดรายงานใด ๆ ภายใต้หรือตรงกับที่มากเกินไป

#!/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 (ซึ่งจะรวมข้อความที่ไม่ใช่ ASCII ในการเข้ารหัสบางส่วนรวมถึง 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;
}

ขอบคุณคำตอบทั้งคู่ ฉันรู้สึกว่าฉันควรทำบางสิ่งเป็นคำตอบที่ดีแม้ว่าทั้งคู่จะให้ regexps ซึ่งฉันต้องการหลีกเลี่ยง เลือกอันนี้เนื่องจากมันให้การอ้างอิงสำหรับรูปแบบ
andrew cooke

@ andrew: regexp ของฉันมีความยืดหยุ่นเพียงพอที่ฉันคาดหวังว่ามันจะทำงานร่วมกับเทอร์มินัลที่มีอยู่ในตอนนี้และอาจใช้กับเทอร์มินัลที่มีอยู่ในวันพรุ่งนี้เช่นกัน ฉันไม่ได้ทดสอบมากนักดังนั้นอาจมีข้อบกพร่อง แต่วิธีการดังกล่าวเป็นไปตามลำดับการควบคุมตามรูปแบบทั่วไปบางอย่าง
Gilles

โปรดระบุวิธีใช้สคริปต์นี้ มันต้องมีอินพุตท่อหรือไม่? หรือข้อโต้แย้งตำแหน่ง?
เทรเวอร์บอยด์สมิ ธ

@TrevorBoydSmith จะทำงานกับอินพุตและเอาต์พุตจะเป็นเอาต์พุตมาตรฐานเสมอเช่นยูทิลิตี้ข้อความทั่วไป
Gilles

อักขระแบบมัลติไบต์นี้ mangles เช่น☺ (\ xe2 \ x98 \ xba) ประโยค [\ x80- \ x9f] ตัดแถบไบต์กลางออก
Jeffrey

31

การอัปเดตคำตอบของ Gilles เพื่อลบ carriage return และทำการลบ backspace ของอักขระก่อนหน้าซึ่งทั้งคู่มีความสำคัญสำหรับฉันสำหรับ typescript ที่สร้างบน 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 ฉันได้พิมพ์โพสต์ด้วยคำถามเดียวกันกับ OP เมื่อฉันชอบข้อความนี้ด้วยสคริปต์ของคุณและของ @Gilles +1 สำหรับคุณทั้งคู่
miracle17

10

ฉันจะใช้sedในกรณีนี้

ทำ:

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

sed -e "s / search / replace / g" เป็นสิ่งมาตรฐาน regex มีการอธิบายดังนี้:

\x1bตรงกับ Escape รหัสสี \[ตรงกับเครื่องหมายวงเล็บเหลี่ยม .\{1,5\}แรกที่ตรงกับ 1 ถึง 5 ของอักขระเดี่ยวใด ๆ ต้องไปที่\เครื่องมือจัดฟันแบบหยิกเพื่อป้องกันไม่ให้เปลือกหอยถูกทำลาย mอักขระตัวสุดท้ายใน regex - โดยปกติจะลากรหัสสี //สตริงว่างสำหรับสิ่งที่จะแทนที่ทุกอย่างด้วย gตรงกับมันหลายครั้งต่อบรรทัด


3
regex แถบนี้มากเกินไป ( foo\e[1m(1m = {กลายเป็นfoo = {แทนที่จะเป็นfoo(m = {) แทนที่.ด้วย[0-9;]มีความแม่นยำมากขึ้น
Lekensteyn

แทนที่.\{1,5\}ด้วย[^m]\{1,5\}การที่ - แต่ยังทราบว่านี้ได้แล้วยังเอาเท่านั้น "กราฟิกกระทำ" รหัส (ผู้ที่จบในm) - สีพื้นย้อนกลับตัวเอียงตัวหนาและรูปแบบ (ที่ใช้ได้)
Hannu

สิ่งนี้จะไม่ลบ\x1b(B(รวมอยู่ในการแสดงผลสีสนิม)
ideasman42

1
ทำไมถึงเป็นเช่นนั้น\x1bและไม่ใช่\033?
atripes

มันอาจจะเป็น\u001bแทน\x1b
yunzen


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ในหน้าจอและการทิ้งบัฟเฟอร์การเลื่อนกลับไปยังไฟล์

สคริปต์คาดหวังต่อไปนี้ใช้สำหรับคุณ

มันได้รับการทดสอบสำหรับ logfiles ที่มีมากถึง 250.000 บรรทัด ในไดเรกทอรีทำงานคุณต้องการ scriptlog ของคุณไฟล์ที่เรียกว่า "เวลา" กับ 10.000.000 เท่าของบรรทัด "1 10" ในนั้นและสคริปต์ ฉันต้องการชื่อของ scriptfile ./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

คำสั่งสำหรับการสร้างไฟล์เวลาสร้างการใช้งาน CPU 100% ในเวลาไม่กี่นาทีและหลังจากนั้นการใช้งานหน่วยความจำของฉันเสร็จสิ้นเป็น 100% และคำสั่งที่ทำงานอยู่ส่งผลให้ "fork: ไม่สามารถจัดสรรหน่วยความจำ" และมันก็ใช้งานไม่ได้ตามที่คาดไว้
barteks2x

มีวิธีที่ง่ายกว่ามากในการสร้างไฟล์กำหนดเวลา เขตข้อมูลคือ " 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

ฉันต้องการใช้เครื่องมือพิเศษในการแปลงเอาต์พุตสคริปต์เป็นข้อความธรรมดาซึ่งได้รับการสนับสนุนอย่างต่อเนื่องและผ่านการทดสอบเป็นอย่างดีโดยใช้ regexp แบบกำหนดเอง ดังนั้นนี่จึงเป็นประโยชน์สำหรับฉัน:

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

คำสั่งสคริปต์รวบรวมเป็นไฟล์ typescript ansi2txt - แปลงรหัส ansi ด้วย escapes เช่น colorcodes, backspaces และอื่น ๆ ให้เป็นข้อความปกติ col-bp - ลบออกอย่างสมบูรณ์

ฉันได้ทดสอบสิ่งนี้กับดิสโก้ Ubuntu ล่าสุดแล้วและใช้งานได้


1

มีansi2txtคำสั่งในcolorized-logsแพ็คเกจบน Ubuntu มันลบรหัสสี ANSI ได้อย่างดี แต่ไม่ได้จัดการกับสิ่งต่าง ๆ เช่นแถบความคืบหน้าที่สร้างขึ้นโดยการเปล่ง^Hหรือ^Mตัวอักษรเพื่อเขียนทับข้อความ col -bสามารถจัดการกับสิ่งเหล่านั้นได้เพื่อผลลัพธ์ที่ดีที่สุดคุณสามารถรวมสองอย่างนี้เข้าด้วยกัน

cat typescript | ansi2txt | col -b

0

ฉันพบว่าเพียงแค่ใช้catคือทั้งหมดที่ฉันต้องการเพื่อดูผลลัพธ์ของscriptใน terminal นี้ไม่ได้ช่วยให้เมื่อเปลี่ยนเส้นทางออกไปยังไฟล์อื่น แต่จะทำให้ผลที่ได้อ่านแตกต่างcat -v, col -bหรือแก้ไขข้อความ

หากต้องการกำจัดสีหรือบันทึกผลลัพธ์ลงในไฟล์ให้คัดลอกและวางผลลัพธ์จากcatตัวแก้ไขข้อความด้วยตนเองหรือไปยังcatคำสั่งอื่นเช่น:

cat > endResult << END
<paste_copied_text_here>
END

1
การscriptวิ่งของคุณรวมเอาท์พุทที่มีรหัสสีติดอยู่ในกรณีของ OP หรือไม่
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:]]

ยินดีต้อนรับสู่ Unix Stackexchange! เมื่อให้คำตอบควรให้คำอธิบายว่าทำไมคำตอบของคุณจึงเป็นคำตอบ
Stephen Rauch


3
นี้จริงจะไม่ทำงานอย่างถูกต้องมันจะไม่ลบเช่นและจะลบจุดสิ้นสุดของบรรทัด01;34m newline (\n)
sorontar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.