การลบรหัสสี ANSI ออกจากสตรีมข้อความ


73

ตรวจสอบผลลัพธ์จาก

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

ในเท็กซ์เอดิเตอร์ (เช่นvi) แสดงสิ่งต่อไปนี้:

^[[37mABC
^[[0m

เราจะลบรหัสสี ANSI ออกจากไฟล์เอาต์พุตได้อย่างไร ฉันคิดว่าวิธีที่ดีที่สุดคือการส่งออกท่อผ่านตัวแก้ไขสตรีม

ต่อไปนี้ใช้ไม่ได้

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

ไม่ใช่คำตอบสำหรับคำถาม แต่คุณยังสามารถไพพ์เอาต์พุตไปยังmoreหรือless -Rซึ่งสามารถแปลรหัสการยกเว้นเป็นสีแทนที่จะเป็นตัวแก้ไขข้อความ
terdon

คำตอบ:


97

ตัวละคร^[[37mและ^[[0mเป็นส่วนหนึ่งของลำดับหนี ANSI (รหัส CSI) ดูข้อมูลจำเพาะเหล่านี้ด้วย

ใช้ GNU sed

sed 's/\x1b\[[0-9;]*m//g'
  • \x1b(หรือ\x1B) คือการหลบหนีอักขระพิเศษ
    ( sedไม่สนับสนุนทางเลือก\eและ\033)
  • \[ เป็นอักขระตัวที่สองของลำดับ escape
  • [0-9;]* คือค่าสี regex
  • m เป็นอักขระตัวสุดท้ายของลำดับ escape

⚠บน MacOS เริ่มต้นsedคำสั่งไม่สนับสนุนอักขระพิเศษเช่น\eเป็นแหลมออกโดยSLMและsteamer25ในการแสดงความคิดเห็น ใช้แทนที่คุณสามารถติดตั้งใช้gsedbrew install gnu-sed

ตัวอย่างที่มีบรรทัดคำสั่งของ OP:   (OP หมายถึงโปสเตอร์ต้นฉบับ)

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

Tom Haleแนะนำให้ลบลำดับ escape อื่น ๆ ทั้งหมดโดยใช้[a-zA-Z]แทนที่จะเป็นตัวอักษรmเฉพาะของโหมดกราฟิก (สี) escape แต่[a-zA-Z]อาจกว้างเกินไปและสามารถลบได้มากเกินไป MichałFaleńskiและMiguel Motaเสนอที่จะลบลำดับการหลบหนีบางอย่างโดยใช้[mGKH]และ[mGKF]ตามลำดับ ต้องระบุBritton KerinKด้วยนอกเหนือจากเพื่อmลบสีออกจากgccข้อผิดพลาด / คำเตือน (อย่าลืมเปลี่ยนเส้นทาง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

การใช้ perl

รุ่นของการsedติดตั้งบนระบบปฏิบัติการบางระบบอาจมีข้อ จำกัด (เช่น macOS) คำสั่งperlมีข้อได้เปรียบในการติดตั้ง / อัปเดตระบบปฏิบัติการได้ง่ายขึ้น อดัมแคทซ์แนะนำให้ใช้\e(เหมือน\x1b) ในPCRE

เลือก regex ของคุณขึ้นอยู่กับจำนวนคำสั่งที่คุณต้องการกรอง:

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

ตัวอย่างที่มีบรรทัดคำสั่งของ OP:

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

การใช้

ตามที่ระบุโดยข้อคิดเห็นของ Stuart Cardallsedบรรทัดคำสั่งนี้ถูกใช้โดยโครงการUltimate Nginx Bad Bot (1,000 ดาว) เพื่อล้างรายงานอีเมล ;-)


2
ขอบคุณสำหรับsedคำสั่งและคำอธิบาย :)
Redsandro

2
รหัสสีบางตัว (เช่นเทอร์มินัล Linux) มีคำนำหน้าเช่น1;31mเพื่อเพิ่ม;regex ของคุณให้ดีขึ้น: cat colored.log | sed -r 's/\x1b\[[0-9;]*m//g'ไม่เช่นนั้นรหัสเหล่านั้นจะไม่ถูกถอดออก
Redsandro

1
นี่ยอดเยี่ยมใช้ในgithub.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/blob/ …เพื่อล้างรายงานอีเมล
Stuart Cardall

2
โปรดทราบว่าเวอร์ชัน OSX ของใช้งานsedไม่ได้กับตัวอย่างที่แสดง แต่เป็นgsedเวอร์ชั่น
slm

2
บริบทเพิ่มเติมสำหรับความคิดเห็นของ slm เกี่ยวกับ OSX sed: ไม่รองรับอักขระควบคุมเช่น \ x1b เช่นstackoverflow.com/a/14881851/93345 คุณจะได้รับคำสั่ง gsed brew install gnu-sedผ่าน
steamer25

21

ฉันได้พบกับตัวกำจัดลำดับการหลบหนีที่ดีกว่า ตรวจสอบสิ่งนี้:

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


2
การปรับปรุงจากคำตอบที่ยอมรับ ( superuser.com/a/380778/46794 ) คืออะไร
Blaisorblade

4
@Blaisorblade มันทำงานบน OS X ในขณะที่sed -rไม่
BVengerov

10

สิ่งที่ปรากฏตามที่ไม่^[เป็นและ; เป็นอักขระ ASCII ที่สร้างโดยหรือ( เครื่องหมายหมายถึงปุ่ม Ctrl) ^[ESCEscCtrl[^

ESCคือ 0x1B เลขฐานสิบหกหรือ 033 ฐานแปดดังนั้นคุณต้องใช้\x1Bหรือ\033ใน regexes ของคุณ:

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

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

6

หากคุณต้องการสิ่งที่เรียบง่ายคุณสามารถใช้โมดูลstrip-ansi ( จำเป็นต้องใช้Node.js ):

$ npm install --global strip-ansi-cli

จากนั้นใช้แบบนี้:

$ strip-ansi < colors.o

หรือเพียงแค่ผ่านสตริง:

$ strip-ansi '^[[37mABC^[[0m'

นี้การใช้งานที่ไร้ประโยชน์cat( UUOC ) - มันควรจะเป็นไปได้ที่จะทำหรืออย่างน้อยstrip-ansi colors.o strip-ansi < colors.o
สกอตต์

1
@Scott แน่นอนคุณสามารถทำได้strip-ansi < colors.oแต่จากประสบการณ์ที่ผู้คนคุ้นเคยกับการวางท่อ ฉันได้อัพเดตคำตอบแล้ว
Sindre Sorhus

ทางออกที่ดีง่าย
Penghe Geng


2

คำถาม "ตอบ" ไม่ทำงานสำหรับฉันดังนั้นฉันสร้าง regex นี้แทนการลบลำดับ escape ที่ผลิตโดย perl Term :: ANSIColor module

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

regex ของ Grawity ควรจะทำงานได้ดี แต่การใช้ + ก็ดูเหมือนว่าจะใช้ได้เช่นกัน


4
(1) คุณหมายถึงThe "answered" questionอะไร คุณหมายถึงคำตอบที่ยอมรับหรือไม่ (2) คำสั่งนี้ใช้ไม่ได้ - ไม่ได้ดำเนินการ - เพราะมีเครื่องหมายคำพูด (ไม่สมดุล) ที่ไม่ตรงกัน (3) นี้การใช้งานที่ไร้ประโยชน์ของcat( UUOC ) - มันควรจะเป็นไปได้ที่จะทำ (4) ใครเคยพูดอะไรเกี่ยวกับรหัสที่อยู่ในไฟล์บ้าง perl -pe command colors.o.o
สกอตต์

2

ฉันเชื่อว่านี่เป็นการลบที่มีสิทธิ์ของลำดับการหลบหนีของ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;'

(โปรดทราบ Perl ว่าเหมือนภาษาอื่น ๆ อีกมากมาย ( แต่ไม่ sed) ยอมรับ\eเป็นตัวหนีEsc, \x1bหรือ\033ตามรหัสที่แสดงในอาคารเป็น^[. ฉันใช้มันที่นี่เพราะมันดูเหมือนง่ายขึ้น.)

คำสั่ง perl นี้ซึ่งคุณสามารถเรียกใช้ทั้งหมดในหนึ่งบรรทัดหากคุณต้องการมีการแทนที่สี่รายการ:

ครั้งแรกไปหลังจาก CSI ลำดับ (ลำดับรหัสการยกเว้นที่เริ่มต้นด้วย "ผู้แนะนำลำดับการควบคุม" ของEsc[ซึ่งครอบคลุมมากกว่าลำดับSelect Rendition เลือกกราฟิคที่ทำขึ้นรหัสสีและตกแต่งข้อความอื่น ๆ )

การแทนที่ครั้งที่สองจะลบลำดับที่เหลือที่เกี่ยวข้องกับตัวอักษรต่อท้ายและยุติด้วย ST (the String Terminator, Esc\) ที่สามทดแทนเป็นสิ่งเดียวกัน แต่ยังช่วยให้ระบบปฏิบัติการคำสั่งลำดับที่จะจบลงด้วยการBEL ( \x07, \007มัก\a)

การแทนที่ครั้งที่สี่จะลบทางหนีที่เหลืออยู่

นอกจากนี้ยังพิจารณาลบอักขระ ASCII อื่น ๆ ศูนย์ความกว้างเช่น BEL และคลุมเครือมากขึ้นอื่น ๆตัวควบคุม C0 และ C1 ฉันใช้อยู่s/[\x00-\x1f\x7f-\x9f\xad]+//gซึ่งรวมถึงการลบและเครื่องหมายขีดสั้น สิ่งนี้ไม่รวมตัวอักษรที่มีความกว้างเป็นศูนย์ความสูงของ Unicode แต่ฉันเชื่อว่ามันครบถ้วนสมบูรณ์สำหรับ ASCII (Unicode \x00- \xff) หากคุณทำสิ่งนี้ให้ลบสิ่งเหล่านี้ออกเนื่องจากพวกเขาสามารถมีส่วนร่วมในลำดับที่ยาวกว่า


1

"tput sgr0" ออกจากตัวควบคุมนี้ ^ (B ^ [
นี่คือรุ่นที่แก้ไขเพื่อดูแล

perl -pe 's/\e[\[\(][0-9;]*[mGKFB]//g' logfile.log

ขอบคุณสำหรับสิ่งนี้ ... สิ่งนี้ได้ผลสำหรับฉันที่จะกำจัดสิ่งtput sgr0ที่ดูเหมือนว่าโซลูชันอื่น ๆ จะไม่สามารถกำจัดได้
TxAG98

0

ฉันมีปัญหาคล้ายกันกับการลบตัวอักษรที่เพิ่มจากการรวบรวมเอาท์พุทโต้ตอบบนสุดผ่าน putty และสิ่งนี้ช่วย:

cat putty1.log | perl -pe 's/\x1b.*?[mGKH]//g'

3
นี้การใช้งานที่ไร้ประโยชน์cat( UUOC ) - มันควรจะเป็นไปได้ที่จะทำ perl -pe command putty1.log
สกอตต์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.