Grep nhiều màu


30

Tôi đang cố gắng để mỗi lệnh grep làm nổi bật kết quả của nó bằng một màu khác nhau. Tôi có thể làm điều đó bằng tay với một dòng như thế này:

ls -l GREP_COLORS='mt=01;32' grep c | GREP_COLORS='mt=01;31' grep o | GREP_COLORS='mt=01;34' grep n | GREP_COLORS='mt=01;36' grep f

Mỗi cnhân vật sẽ được tô sáng màu xanh lá cây và mọi onhân vật sẽ được tô sáng màu đỏ, v.v ...

Để ví dụ này hoạt động, bạn sẽ cần đảm bảo rằng bạn luôn có --color=alwayscác lệnh grep của mình. Tôi đã thiết lập điều này trong .bashrc grep của mình để luôn có màu sắc:

export GREP_OPTIONS='--color=always'


Những gì tôi đang cố gắng thực hiện là bọc chức năng này bằng một bí danh để tôi chỉ có thể gọi grepvà có một GREP_COLORSgiá trị khác nhau mỗi lần. Tôi hiểu việc xem xét nhiều shell cho mỗi grep đường ống mới và tôi đang cố gắng vượt qua điều này bằng cách tạo một số tệp (một cho mỗi màu), để chỉ ra rằng chúng đã được sử dụng.

Tôi đã thực hiện một số nỗ lực nhưng kỳ lạ thay, cái này dường như hoạt động "tốt nhất". Tôi có cái này trong .bashrc:

alias mg="mygrep"
mygrep(){
    # define possible colors
    COLORS=("01;32" "01;31" "01;34" "01;36")
    COUNTER=0
    NUM=0
    # as long as the color has already been used, keep searching
    while [ -f /home/lior/Desktop/mygrep_$NUM ]; do
        # get a random index
        let NUM=`shuf --input-range=0-$(( ${#COLORS[*]} - 1 )) | head -1`
        wait ${!}
        $(( COUNTER+=1 ))
        if [ "$COUNTER" -ge ${#COLORS[@]} ]; then
            # remove all color locks
            rm /home/lior/Desktop/mygrep_*
            wait ${!}
        fi
    done
    # mark this color as used
    touch /home/lior/Desktop/mygrep_$NUM
    wait ${!}

    # lets go!
    GREP_COLORS="mt=${COLORS[$NUM]}" grep "$@"
}

Tôi đang sử dụng bí danh này như vậy:

ll | mg c | mg o | mg n | mg f

Kết quả khá tuyệt. Tuy nhiên, có một số lỗi hơi khác nhau mỗi lần. Dưới đây là một vài ảnh chụp màn hình:

Có vẻ như shell đi qua từng lệnh ống, hàm trước chưa hoàn thành việc thực thi. Nó cố gắng loại bỏ các tập tin không còn tồn tại nữa. Tôi không chắc chắn những command not foundlỗi khác đến từ đâu.

Như bạn có thể thấy, tôi đã đưa vào một số waitlệnh để thử hoàn thành thao tác tệp nhưng điều này dường như không hoạt động tốt. Một điều khác tôi đã thử là sử dụng bộ nhớ dùng chung /dev/shmnhưng nó mang lại kết quả tương tự.

Làm thế nào tôi sẽ đi về kết quả tôi muốn?

Chú thích:

Tôi đang tìm kiếm câu trả lời chỉ đơn giản là bọc lệnh grep vì nó có rất nhiều chức năng mà tôi muốn sử dụng và có ý định chèn logic khác giữa các đường ống, vì vậy tôi không muốn cung cấp tất cả các thuật ngữ tìm kiếm cùng một lúc. Tôi cũng không tìm kiếm các công cụ "grep like" khác. Xin lỗi @terdon , người đã đăng một đề xuất perl tuyệt vời.


Ví dụ đầu tiên của bạn không khớp với những gì bạn đang giải thích trong phần còn lại, chỉ nói.
Bernhard

@bernhard Tôi không hiểu ý bạn là gì .. Ý định của tôi là sử dụng bí danh của mình như một phần của lệnh lớn hơn bằng cách sử dụng đường ống ... Xin vui lòng cho tôi biết bạn đang nói về mâu thuẫn nào ...
Lix

Tôi nghĩ bạn cũng muốn sử dụng bí danh của mình bên ngoài đường ống. Dù sao, ví dụ đầu tiên của bạn không làm việc cho tôi. Bạn đã thử alias mg="mygrep; grep"chưa
Bernhard

@Bernhard - Tôi đang làm việc trên hộp Ubuntu 12.04. Tôi sẽ không ngạc nhiên nếu có sự khác biệt nhỏ ... Tôi đã thử đề xuất của bạn, vấn đề là nó tự mygrep;biến thành một lệnh mới và luồng dữ liệu bị mất. Các đường ống đến từ lssẽ được chuyển đến mygrep;và không đến grep. Ít nhất đó là cách tôi hiểu nó.
Lix

@Bernhard - Ah .. Tôi nghĩ tôi biết tại sao nó không hiệu quả với bạn. Bạn cần đảm bảo rằng bạn có --color=alwaystrên tất cả các lệnh grep của bạn. Tôi đã đặt nó trên toàn cầu trong tôi .bashrc. Tôi đã chỉnh sửa nó vào bài viết.
Lix

Câu trả lời:


6

Đây là một cách tiếp cận khác nhau. Tôi có một đoạn script Perl nhỏ mà tôi đã đăng trong một câu trả lời khác sẽ làm nổi bật người dùng được cung cấp các mẫu với các màu khác nhau. Một phiên bản sửa đổi một chút của tập lệnh sẽ hoạt động như grepsau:

#!/usr/bin/env perl
use Getopt::Std;
use strict;
use Term::ANSIColor; 

my %opts;
getopts('hic:l:',\%opts);
    if ($opts{h}){
      print<<EoF; 
Use -l to specify the pattern(s) to highlight. To specify more than one 
pattern use commas. 

-l : A Perl regular expression to be colored. Multiple expressions can be
     passed as comma separated values: -l foo,bar,baz
-i : makes the search case sensitive
-c : comma separated list of colors;

EoF
      exit(0);
    }

my $case_sensitive=$opts{i}||undef;
my @color=('bold red','bold blue', 'bold yellow', 'bold green', 
       'bold magenta', 'bold cyan', 'yellow on_blue', 
       'bright_white on_yellow', 'bright_yellow on_red', 'white on_black');
if ($opts{c}) {
   @color=split(/,/,$opts{c});
}
my @patterns;
if($opts{l}){
     @patterns=split(/,/,$opts{l});
}
else{
    $patterns[0]='\*';
}

# Setting $| to non-zero forces a flush right away and after 
# every write or print on the currently selected output channel. 
$|=1;

while (my $line=<>) 
{ 
    my $want=0;
    for (my $c=0; $c<=$#patterns; $c++){
    if($case_sensitive){
        if($line=~/$patterns[$c]/){
           $line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ge;
           $want++;
        }
    }
    else{
        if($line=~/$patterns[$c]/i){
          $line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ige;
          $want++;
        }
      }
    }
print STDOUT $line if $want>0;
}

Nếu bạn lưu tập lệnh cgrepđó như một nơi nào đó trong bạn PATHvà làm cho nó có thể thực thi được, bạn có thể chỉ định tối đa 10 mẫu khác nhau, mỗi mẫu sẽ được in bằng một màu khác nhau:

nhập mô tả hình ảnh ở đây

$ cgrep -h
Use -l to specify the pattern(s) to highlight. To specify more than one 
pattern use commas. 

-l : A Perl regular expression to be colored. Multiple expressions can be
     passed as comma separated values: -l foo,bar,baz
-i : makes the search case sensitive
-c : comma separated list of colors;

5

Mỗi lệnh gọi greptrong một đường ống chạy trong một vỏ riêng biệt, vì vậy bạn sẽ cần phải vượt qua một số trạng thái giữa chúng. Giải pháp sau đây là một cách thô sơ để xử lý điều đó với một tệp giữ chỉ mục màu và tệp khóa đảm bảo các cuộc gọi đồng thời không đọc cùng một giá trị:

#!/usr/bin/env bash
color_index_file=~/.gitcolor
color_index_lock_file=/tmp/$(basename $0)

colors=()
for index in {31..34}
do
    colors+=("01;$index")
done

until mkdir "$color_index_lock_file" 2>/dev/null
do
    :
done

color_index=$(($(cat "$color_index_file" || echo 0) + 1))

if [[ $color_index -ge ${#colors[@]} ]]
then
    color_index=0
fi

printf "$color_index" > "$color_index_file"
rmdir "$color_index_lock_file"

GREP_COLORS="mt=01;${colors[$color_index]}" grep --color=always "$@"

Kiểm tra giả sử bạn đã đặt tên cho bản sao của mình cgrepvà đặt nó vào PATH:

echo foobarbaz | cgrep foo | cgrep bar | cgrep baz

Các biến duy nhất thực sự cần được duy trì là COLOR_INDEXGREP_COLORS. Tôi đã thử xuất chúng ở cuối hàm mà không thành công. Đó có phải ý của bạn? Đơn giản là có export VAR, phải không?
Lix

Oh - và yea ​​.. typo ngớ ngẩn ở đó với COLOR_TOGGLE. Cảm ơn vì đã bắt nó :)
Lix

1
@ l0b0 Việc xuất cũng không hiệu quả đối với tôi, phải tải xuống cho đến khi nó thực sự trả lời được câu hỏi.
Bernhard

@Bernhard Điều này có hiệu quả với bạn không?
l0b0

Cảm ơn vì đầu vào của bạn! Tôi đã kết hợp grep "$@"đề xuất của bạn - đã sắp xếp bí danh để chạy hàm và sau đó grep.
Lix

1

Nếu bạn tốt với các biểu thức thông thường, Bạn có thể muốn kiểm tra grc và grcat. grc gọi grcat.

grcat sử dụng các tệp cấu hình trong đó bạn có thể thêm các biểu thức thông thường để khớp văn bản sẽ được hiển thị trong mỗi màu. Nó cũng có một số tùy chọn khác. Nó mặc định để tô màu các tệp nhật ký hệ thống.

Tùy thuộc vào những gì bạn có trong kịch bản cuối cùng của mình, bạn có thể tô màu đầu ra của mình chỉ bằng một lệnh.

Thủ thuật là chỉ định chính xác các biểu thức chính xác cho từng "trường" trong nguồn dữ liệu của bạn. Điều này sẽ dễ dàng hơn rất nhiều nếu dữ liệu của bạn tương đối đồng đều về cấu trúc.

Lần trước tôi đã thử nó, tôi đã không đi quá xa, nhưng tôi có thể có một lần nữa vì nó tốt hơn một chút về regexes so với lúc đó.

Ngoài ra còn có lệnh tput có thể được sử dụng để gửi thông tin (như thay đổi màu sắc) trực tiếp đến thiết bị đầu cuối của bạn.

Cả hai cách tiếp cận được bao phủ bởi bài viết dưới đây. Nó nói về lệnh find, nhưng nó có thể được áp dụng cho đầu ra của bất kỳ lệnh nào.

Đầu ra TÌM màu?

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.