Grep Berwarna-warni

30

Saya mencoba untuk mendapatkan setiap perintah grep untuk menyorot hasilnya dalam warna yang berbeda. Saya bisa melakukannya secara manual dengan garis seperti ini:

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

Setiap ckarakter akan disorot dalam warna hijau dan setiap okarakter akan disorot dalam warna merah, dll ...

Agar contoh ini berfungsi, Anda harus memastikan bahwa Anda selalu memiliki --color=alwaysperintah grep. Saya telah mengatur ini di .bashrc grep saya agar selalu memiliki warna:

export GREP_OPTIONS='--color=always'


Apa yang saya coba capai adalah membungkus fungsi ini dengan alias sehingga saya bisa menelepon grepdan memiliki GREP_COLORSnilai yang berbeda setiap kali. Saya memahami pertimbangan beberapa shell untuk setiap grep yang disalurkan baru dan saya mencoba untuk mengatasi ini dengan membuat beberapa file (satu untuk setiap warna), untuk menunjukkan bahwa mereka telah digunakan.

Saya telah melakukan beberapa upaya tetapi anehnya, yang ini tampaknya bekerja dengan "yang terbaik". Saya memiliki ini di .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 "$@"
}

Saya menggunakan alias ini seperti ini:

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

Hasilnya cukup keren. Namun ada beberapa kesalahan yang sedikit berbeda setiap kali. Berikut ini beberapa tangkapan layar:

Sepertinya shell melewati setiap perintah pipa, fungsi sebelumnya belum menyelesaikan eksekusi. Mencoba menghapus file yang tidak ada lagi. Saya tidak terlalu yakin dari mana command not foundkesalahan-kesalahan lain itu berasal.

Seperti yang Anda lihat, saya telah memasukkan beberapa waitperintah untuk mencoba membiarkan manipulasi file selesai tetapi ini tampaknya tidak berfungsi dengan baik. Hal lain yang sudah saya coba adalah menggunakan memori bersama /dev/shmtetapi menghasilkan hasil yang serupa.

Bagaimana cara saya mendapatkan hasil yang saya inginkan?

catatan:

Saya mencari jawaban yang hanya membungkus perintah grep karena memiliki banyak fungsi yang ingin saya gunakan dan bermaksud untuk memasukkan logika lain di antara pipa, jadi saya tidak ingin memberikan semua istilah pencarian sekaligus. Saya juga tidak mencari alat "grep like" lainnya. Maaf untuk @terdon yang telah memposting saran perl yang mengagumkan.

Lix
sumber
Contoh pertama Anda tidak cocok dengan apa yang Anda jelaskan di bagian yang tersisa, hanya mengatakan.
Bernhard
@bernhard Saya tidak mengerti maksud Anda .. Maksud saya adalah menggunakan alias saya sebagai bagian dari perintah yang lebih besar menggunakan perpipaan ... Tolong beri tahu saya apa kontradiksi yang Anda bicarakan ...
Lix
Saya pikir Anda juga ingin menggunakan alias di luar pipa. Bagaimanapun, contoh pertama Anda tidak bekerja untuk saya. Apakah kamu sudah mencoba alias mg="mygrep; grep"?
Bernhard
@Bernhard - Saya sedang mengerjakan kotak ubuntu 12.04. Saya tidak akan terkejut jika ada sedikit perbedaan ... Saya sudah mencoba saran Anda, masalah dengan itu adalah yang mygrep;berubah menjadi perintah baru dalam dirinya sendiri dan aliran data hilang. Pipa yang masuk dari lsakan diteruskan ke mygrep;dan tidak untuk grep. Setidaknya begitulah cara saya memahaminya.
Lix
@ Bernhard - Ah .. Saya rasa saya tahu mengapa itu tidak berhasil untuk Anda. Anda perlu memastikan bahwa Anda memiliki --color=alwayssemua perintah grep Anda. Saya telah mengaturnya secara global di .bashrc. Saya sudah mengeditnya di posting.
Lix

Jawaban:

6

Ini pendekatan yang berbeda. Saya punya skrip Perl kecil yang sudah saya posting di jawaban lain yang akan menyoroti pola yang disediakan pengguna dalam warna yang berbeda. Versi skrip yang sedikit dimodifikasi akan bertindak seperti grep:

#!/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;
}

Jika Anda menyimpan skrip itu sebagai bagian dari skrip cgrepAnda PATHdan membuatnya dapat dieksekusi, Anda dapat menentukan hingga 10 pola berbeda, yang masing-masing akan dicetak dalam warna berbeda:

masukkan deskripsi gambar di sini

$ 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;
terdon
sumber
5

Setiap doa grepdalam pipa berjalan di shell yang terpisah, jadi Anda harus melewati beberapa keadaan di antara mereka. Solusi berikut adalah cara kasar untuk mengatasinya dengan file yang menjaga indeks warna dan file kunci yang memastikan bahwa panggilan simultan tidak membaca nilai yang sama:

#!/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 "$@"

Tes dengan asumsi Anda telah memberi nama salinan Anda cgrepdan meletakkannya di PATH:

echo foobarbaz | cgrep foo | cgrep bar | cgrep baz
l0b0
sumber
Satu-satunya variabel yang benar-benar perlu dipertahankan adalah COLOR_INDEXdan GREP_COLORS. Saya mencoba mengekspor ini di akhir fungsi tanpa hasil. Apakah itu yang kamu maksud? Cukup untuk dimiliki export VAR, bukan?
Lix
Oh - dan ya .. salah ketik konyol dengan COLOR_TOGGLE. Terima kasih sudah menangkapnya :)
Lix
1
@ l0b0 Mengekspor tidak bekerja untuk saya juga, harus downvote untuk saat ini sampai benar-benar menjawab pertanyaan.
Bernhard
@ Bernhard Apakah ini cocok untuk Anda?
l0b0
Terima kasih atas masukan Anda! Saya telah memasukkan grep "$@"saran Anda - yang mengurutkan alias untuk menjalankan fungsi lalu grep.
Lix
1

Jika Anda mahir dengan ekspresi reguler, Anda mungkin ingin memeriksa grc dan grcat. grc memanggil grcat.

grcat menggunakan file konfigurasi tempat Anda dapat menambahkan ekspresi reguler untuk mencocokkan teks yang akan ditampilkan di setiap warna. Ini juga memiliki sejumlah opsi lain. Ini default untuk mewarnai file log sistem.

Tergantung pada apa yang ada dalam pikiran Anda untuk skrip akhir Anda, Anda mungkin dapat mewarnai hasil Anda hanya dengan satu perintah.

Caranya adalah menentukan regex dengan benar untuk setiap "bidang" di sumber data Anda. Ini akan jauh lebih mudah jika struktur data Anda relatif seragam.

Terakhir kali saya mencobanya, saya tidak terlalu jauh, tetapi saya mungkin harus mencoba lagi karena saya sedikit lebih baik di regex daripada saya dulu.

Ada juga perintah tput yang dapat digunakan untuk mengirim informasi (seperti perubahan warna) langsung ke perangkat terminal Anda.

Kedua pendekatan tersebut dicakup oleh pos di bawah ini. Ini berbicara tentang perintah find, tetapi dapat diterapkan pada output dari perintah apa pun.

Output FIND berwarna?

Joe
sumber