2013-02-06 22 views
6

Làm cách nào để làm cho độ sâu của màu grep thoát ra khi grepping đầu ra đường ống? Tôi rất vui khi sử dụng cái gì khác (perl?) Thay vì grep.grep qua văn bản màu, ví dụ: gcc | colorgcc | grep regexp

usercase My: Tôi muốn

gcc foobar.c | colorgcc | grep regexp 
ls --color | grep filename 

làm việc độc đáo với màu sắc (trên một thiết bị đầu cuối sử dụng unix ANSI thoát).

Các ví dụ kiểm tra về hành vi tôi muốn:

echo -e "he\e[35mllo\e[00m" world |grep hell ==> he\e[35mllo\e[00m world 
echo -e "\e[35m removed line\nhello\e[00m" world |grep hell ==> \e[35mhello\e[00m world 
echo -e "\e[35m rem\e[1moved line\nhello\e[00m" world | grep hell ==> \e35m\e1mhello\e[00m world 

Hiện tại dòng đầu tiên cho chuỗi rỗng, và một trong những thứ hai mang đến cho chuỗi uncolorised 'hello \ e [00 Tr thế giới'. Ở đây \ e [35m và \ e00m là các biến tố màu (thuộc tính): màu của một chữ cái được xác định bởi một vài chuỗi màu (thuộc tính) cuối cùng của mẫu \ e [P1; P2; .. m trong đó P1, P2, v.v ... là dãy số; \ e [P1m \ e [P2m tương đương với \ e [P1; P2m. \ e [0m làm cho màu mặc định và quên tất cả các \ e [.. m chuỗi trước đó: \ e [34m \ e [0m tương đương với \ e [0m. Có một số thuộc tính độc lập (in đậm, màu nền, màu của nền trước/chữ cái); mỗi số trong chuỗi thoát chỉ ảnh hưởng đến một số. Như vậy \ e [1m \ e [35m tương đương với \ e [1; 35m nhưng không phải \ e [35; 1m và \ e [35m; tuy nhiên, \ e [34m \ e [35m tương đương với \ e [35m vì cả hai đều ảnh hưởng đến cùng một attirbute (cụ thể là, màu của chữ cái/chữ cái trước).

+2

đâm đầu tiên tại một giải pháp: 'gcc foobar.c | colorgcc | ít hơn -R +/regexp'. 'less -R' hiểu mã màu và sẽ tìm kiếm xung quanh chúng. – nneonneo

Trả lời

2

Đây là một vấn đề thực sự thú vị, đây là những gì tôi nghĩ ra. Nó là khá xấu xí nhưng có vẻ như để hoàn thành công việc:

sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' | 
    grep `sed 's/./\0\\\\(\x1b\\\\[[0-9]*m\\\\(;[0-9]*m\\\\)*\\\\)*/g' <<< hell` 

Thuật ngữ mà bạn đang tìm kiếm sẽ được đặt vào cuối (thay cho "địa ngục"), đây là một vài ví dụ với các văn bản mà bạn cung cấp (sử dụng hexdump để hiển thị màu sắc):

$ echo -e "he\e[35mllo\e[00m" world | 
> sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' | 
> grep `sed 's/./\0\\\\(\x1b\\\\[[0-9]*m\\\\(;[0-9]*m\\\\)*\\\\)*/g' <<< hell` | 
> hexdump -C 
00000000 1b 5b 30 6d 68 65 1b 5b 33 35 6d 6c 6c 6f 1b 5b |.[0mhe.[35mllo.[| 
00000010 30 30 6d 20 77 6f 72 6c 64 0a     |00m world.| 
0000001a 

$ echo -e "\e[35m removed line\nhello\e[00m" world | 
> sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' | 
> grep `sed 's/./\0\\\\(\x1b\\\\[[0-9]*m\\\\(;[0-9]*m\\\\)*\\\\)*/g' <<< hell` | 
> hexdump -C 
00000000 1b 5b 33 35 6d 68 65 6c 6c 6f 1b 5b 30 30 6d 20 |.[35mhello.[00m | 
00000010 77 6f 72 6c 64 0a         |world.| 
00000016 

lệnh sed đầu tiên prepends các thiết lập màu hiện tại đến đầu của mỗi dòng, đó là cần thiết ví dụ thứ hai của bạn, nơi màu được đặt trên một dòng mà grep sẽ bỏ qua. Lệnh sed là đối số để grep chèn một regex sẽ khớp với bất kỳ số lần thoát màu nào giữa mỗi ký tự trong cụm từ tìm kiếm.

Dưới đây là phiên bản egrep:

sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' | 
    egrep `sed 's/./\0(\x1b\\\\[[0-9]*m(;[0-9]*m)*)*/g' <<< hell` 
+0

Cảm ơn! Điều này không hoạt động chính xác: echo -e "\ e [35m bị xóa \ e [0m dòng \ nh \ e [34mel \ e [32mlo \ e [00m" –

+0

oh xin lỗi! không, nó hoạt động tốt. nhưng nó làm việc với regexps tùy ý? Nó dường như không hoạt động nếu tôi thay thế 'grep' cuối cùng bằng 'egrep' –

+0

Nếu bạn thay thế grep bằng egrep, thì bạn có thể xóa tất cả các dấu gạch chéo ngược trong lệnh sed thứ hai xuất hiện ngay trước cả '(' hoặc ')' . Đã thêm phần này vào bản chỉnh sửa. –