กรองเอาท์พุทของคำสั่งตามสี


13

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

ฉันจะกรองข้อความที่ไม่ใช่สีแดงได้อย่างไร

รหัสหลอก:

dolongtask | grep -color red

แก้ไข

คำสั่ง outputs สีอื่น ๆ เป็นอย่างดีและผมจะต้องสามารถที่จะกรองออกข้อความทั้งหมดที่ไม่ได้เป็นสีแดง นอกจากนี้การระบายสีข้อความเป็นแบบหลายบรรทัด


1
ฉันขอโทษที่ถามชัดเจน - แต่เอาต์พุตทั้งหมดเปิดอยู่>&1? ฉันหมายความว่าสิ่งสีแดงจะไม่หายไปถ้าคุณ2>/dev/nullใช่มั้ย
mikeserv

คำตอบ:


15

การสลับสีทำได้โดยใช้ลำดับการหลีกเลี่ยงที่ฝังอยู่ในข้อความ โปรแกรมมักจะออกANSI escape sequencesเนื่องจากนั่นคือสิ่งที่เทอร์มินัลทั้งหมดรองรับในปัจจุบัน

ลำดับการหลบหนีเพื่อเปลี่ยนสีพื้นหน้าเป็นสีแดงคือ\e[31mซึ่ง\eกำหนดอักขระการหลีกเลี่ยง (ฐานแปด 033 เลขฐานสิบหก 1b หรือที่เรียกว่า ESC ^[และชื่ออื่น ๆ อีกมากมาย) ตัวเลขในช่วง 30–39 ตั้งค่าสีพื้นหน้า หมายเลขอื่นตั้งค่าคุณลักษณะที่แตกต่าง \e[0mรีเซ็ตแอตทริบิวต์ทั้งหมดเป็นค่าเริ่มต้น เรียกใช้cat -vเพื่อตรวจสอบว่าโปรแกรมพิมพ์ออกมาอย่างไรมันอาจใช้ตัวแปรบางตัวเช่น\e[0;31mเพื่อรีเซ็ตคุณสมบัติทั้งหมดเป็นครั้งแรกหรือ\e[3;31เพื่อเปิดใช้ตัวเอียง (ซึ่งเทอร์มินัลจำนวนมากไม่รองรับ)

ใน ksh, bash หรือ zsh, คุณสามารถใช้$'…'เพื่อเปิดใช้งานเครื่องหมายแบคสแลชที่อยู่ในเครื่องหมายคำพูด, ซึ่งช่วยให้คุณพิมพ์$'\e'เพื่อรับอักขระ escape โปรดทราบว่าคุณจะต้องเป็นสองเท่าทับขวาใด ๆ grepที่คุณต้องการที่จะส่งผ่านไปยัง ใน/bin/shคุณสามารถใช้"$(printf \\e)"หรือพิมพ์ตัวอักษรยกเว้นตัวอักษร

ด้วยgrep -oตัวเลือกGNU ข้อมูลโค้ดต่อไปนี้จะกรองข้อความสีแดงโดยสันนิษฐานว่ามันเริ่มต้นด้วยลำดับการหลบหนี\e[31mลงท้ายด้วยตัวใดตัวหนึ่ง\e[0mหรือ\e[30mในบรรทัดเดียวกันและไม่มีลำดับ escape แบบฝัง

grep -Eo $'\e\\[31m[^\e]*\e\\[[03]?m'

awkตัวอย่างต่อไปนี้จะแยกข้อความสีแดงแม้ว่าจะเป็นหลายบรรทัดก็ตาม

awk -v RS='\033' '
    match($0, /^\[[0-9;]*m/) {
        color = ";" substr($0, 2, RLENGTH-2) ";";
        $0 = substr($0, RLENGTH+1);
        gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
        red = (color ~ /1;*$/)
    }
    red'

นี่คือรูปแบบที่ยังคงคำสั่งเปลี่ยนสีซึ่งอาจเป็นประโยชน์หากคุณกรองหลายสี (ที่นี่เป็นสีแดงและสีม่วงแดง)

awk -v RS='\033' '
    match($0, /^\[[0-9;]*m/) {
        color = ";" substr($0, 2, RLENGTH-2) ";";
        printf "\033%s", substr($0, 1, RLENGTH);
        $0 = substr($0, RLENGTH+1);
        gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
        desired = (color ~ /[15];*$/)
    }
    desired'

โซลูชัน awk ใช้งานได้สำหรับฉัน มีวิธีเก็บรักษาสีเอาท์พุทหรือไม่?
km6zla

@ ogc-nick คุณต้องการเอาต์พุตสีแดงทั้งหมดหรือไม่ printf '\e[31m'; awk …; printf '\e[0m'
Gilles 'SO- หยุดความชั่วร้าย'

สำหรับสีใดก็ตามที่ฉันกำลังกรองเพื่อรักษาไว้ในผลลัพธ์
km6zla

@ ogc-nick ดูการแก้ไขของฉัน
Gilles 'หยุดชั่วร้าย'

6

คุณสามารถมองหาตัวควบคุม grep ซึ่งบางตัวทำหน้าที่สร้างสีสันให้กับเทอร์มินัล

dolongtask | grep '[[:cntrl:]]'

ตัวอย่างเช่นสิ่งนี้สะท้อนถึง "การทดสอบ" สีแดงเป็น grep ซึ่งพบว่ามันถูกล้อมรอบด้วยอักขระควบคุม:

$ echo -e '\033[00;31mtest\033[00m' | grep --color=none '[[:cntrl:]]'
test     <-- in red

--color=noneเป็นเพียงเพื่อให้แน่ใจว่า grep ใช้ไม่ได้ colorization ของตัวเองเพื่อการส่งออกจับคู่ แต่พิมพ์สายทั้งนับถือเพื่อให้ตัวควบคุมจะถูกตีความโดยเปลือก


ดี ฉันสงสัยว่าจะไปให้ไกลกว่านี้ได้ไหมและทำสิ่งที่ชอบgrep -E $'\033\[0?[01];31m.+?\033\[0?0m'หรือgrep -Po '\033\[0?[01]+;31m\K.+?(?=\033\[0?0m)'เพื่อทดสอบหาสีแดงโดยเฉพาะ?
ขับเหล็ก

ฉันเริ่มต้นขึ้นมาพร้อมกับ regexes เช่นคนที่คุณแนะนำ แต่ก่อนที่ฉันจะได้รับพวกเขาในการทำงานฉัน stumbled [[:cntrl:]]เมื่อ ฉันทดสอบคุณแล้วและมันก็ใช้ได้กับฉันเช่น การจับคู่สีแดงและไม่สามารถจับคู่สีอื่น ๆ
savanto

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