it-swarm-id.com

Yakinkan grep untuk menampilkan semua lini, bukan hanya yang cocok

Katakanlah saya memiliki file berikut:

$ cat test

test line 1
test line 2
line without the search Word
another line without it
test line 3 with two test words
test line 4

Secara default, grep mengembalikan setiap baris yang berisi istilah pencarian:

$ grep test test

test line 1
test line 2
test line 3 with two test words
test line 4

Melewati --color parameter ke grep akan membuatnya menyorot bagian dari baris yang cocok dengan ekspresi pencarian, tetapi masih hanya mengembalikan baris yang mengandung ekspresi. Apakah ada cara untuk mendapatkan grep untuk menghasilkan setiap baris dalam file sumber, tetapi sorot yang cocok?

Peretasan mengerikan saya saat ini untuk mencapai hal ini (setidaknya pada file yang tidak memiliki 10.000+ baris berturut-turut tanpa kecocokan) adalah:

$ grep -B 9999 -A 9999 test test

Screenshot of the two commands

Jika grep tidak dapat melakukan ini, apakah ada alat baris perintah lain yang menawarkan fungsi yang sama? Saya telah mengutak-atik ack , tetapi tampaknya tidak memiliki opsi untuk itu juga.

127
Michael Mrozek
grep --color -E "test|$" yourfile

Apa yang kami lakukan di sini cocok dengan $ pola dan pola tes, jelas $ tidak memiliki apa pun untuk diwarnai sehingga hanya pola tes yang mendapat warna. -E hanya menyalakan pencocokan regex yang diperluas.

Anda dapat membuat fungsi dengan mudah seperti ini:

highlight () { grep --color -E "$1|$" "${@:1}" ; }
194
jacksonh
ack --passthru --color string file

untuk Ubuntu dan Debian, gunakan ack-grep, bukan ack

ack-grep --passthru --color string file

Cara lain untuk melakukan ini dengan benar dan dengan mudah dengan grep (selain menggunakan dua regex dengan pergantian seperti pada jawaban yang diterima) adalah melalui pola nol (dan masing-masing string nol).
Ini harus bekerja sama baiknya dengan keduanya -E dan -F beralih sejak, sesuai standar :

-E
    Match using extended regular expressions. 
    [...] A null ERE shall match every line.

dan

-F
    Match using fixed strings.
    [...] A null string shall match every line.

Jadi itu hanya masalah berlari

grep -E -e '' -e 'pattern' infile

dan masing-masing

grep -F -e '' -e 'string' infile
13
don_crissti

Saya memiliki fungsi berikut yang saya gunakan untuk hal-hal seperti:

highlight () {
    Perl -pe "s/$1/\e[1;31;43m$&\e[0m/g"
}

Secara internal terlihat agak jelek, itu bagus dan mudah digunakan, seperti:

cat some_file.txt | highlight some_Word

atau, untuk contoh yang sedikit lebih nyata:

tail -f console.log | highlight ERROR

Anda dapat mengubah warna menjadi apa pun yang Anda suka (yang mungkin sulit dengan grep - Saya tidak yakin) dengan mengubah 1 dan 31 dan 43 (setelah \e[) dengan nilai yang berbeda. kode untuk digunakan adalah semua lebih dari tempat , tapi inilah intro cepat: 1 huruf tebal teks, 31 membuatnya merah, dan 43 memberikan latar belakang kuning. 32 atau 33 akan berbeda warna, dan 44 atau 45 akan menjadi latar belakang yang berbeda: Anda mendapatkan ide. Anda bahkan dapat membuatnya berkedip (dengan 5) jika Anda cenderung.

Ini tidak menggunakan modul Perl khusus, dan Perl hampir ada di mana-mana, jadi saya berharap ini berfungsi hampir di mana saja. Solusi grep sangat pintar, tetapi --color switch on grep tidak tersedia di mana-mana. Sebagai contoh, saya baru saja mencoba solusi ini pada kotak Solaris yang menjalankan bash, dan ksh lain yang sedang berjalan, dan mesin Mac OS X lokal saya menjalankan zsh. Semua bekerja dengan baik. Solaris tersedak grep --color solusi, namun.

Ack juga luar biasa, dan saya merekomendasikannya kepada siapa saja yang belum menemukannya, tapi saya punya beberapa masalah menginstalnya pada beberapa dari banyak server yang saya kerjakan. (Saya lupa mengapa: Saya pikir terkait dengan modul Perl yang diperlukan.)

Karena saya tidak berpikir saya pernah bekerja pada kotak Unix yang tidak telah Perl diinstal (dengan pengecualian sistem tipe tertanam, router Linksys, dan semacamnya) Saya akan mengatakan ini cukup banyak solusi yang bisa digunakan secara universal.

11
iconoclast

Alih-alih menggunakan Grep, Anda dapat menggunakan Lebih Sedikit:

less file

Cari seperti ini: /pattern Enter

Ini akan:

  1. gulir ke baris pertama yang cocok
  2. keluarkan setiap baris mulai dari sana
  3. sorot semua pertandingan

Untuk menggulir ke baris yang cocok berikutnya: n

Untuk menggulir ke baris yang cocok sebelumnya: N

Untuk beralih menyoroti: Esc u

Anda juga dapat mengubah menyoroti warna jika Anda suka.

3
Steven Penny

Anda dapat mencoba:

Perl -MTERM::ANSIColor -nle '/pattern/ ? print colored($_, 'color') : print' test

Namun tidak terlalu portabel, dan bahkan jika Perl diinstal, Anda mungkin perlu mengunduh modul lain. Selain itu akan mewarnai seluruh baris, bukan hanya kata pencarian.

2
gvkv

Tidak ada jawaban yang diberikan sejauh ini yang memberikan solusi portable .

Ini adalah portable1 Fungsi Shell I sudah diposting dalam pertanyaan duplikat tertutup yang tidak memerlukan alat non-standar atau ekstensi non-standar yang disediakan dengan Perl, ack, ggrep, gsed, bash dan sejenisnya tetapi hanya membutuhkan POSIX Shell dan utilitas wajib POSIX sed dan printf:

grepc()
{
  pattern=$1
  shift
  esc=$(printf "\033")
  sed 's"'"$pattern"'"'$esc'[32m&'$esc'[0m"g' "[email protected]"
}

Anda dapat menggunakannya seperti itu:

grepc string_to_search [file ...]

Warna highlight dapat disesuaikan dengan menggunakan salah satu kode ini dalam argumen perintah sed (32m menjadi hijau di sini):

30m black
31m red
33m yellow
34m blue
35m Magenta
36m cyan
37m white
7m reverse video

1 Selama terminal Anda mendukung urutan pelolosan warna ANSI.

2
jlliagre

ripgrep

Gunakan ripgrep dengan --passthru parameter:

rg --passthru pattern file.txt

Ini adalah salah satu alat grepping tercepat , karena ini dibangun di atas mesin regex Rust yang menggunakan automata terbatas, SIMD dan optimasi literal agresif untuk membuat pencarian sangat cepat.

--passthru - Cetak baris yang cocok dan yang tidak cocok.

Cara lain untuk mencapai efek serupa adalah dengan memodifikasi pola Anda agar cocok dengan string kosong. Misalnya, jika Anda mencari menggunakan rg foo lalu menggunakan rg "^|foo" Sebaliknya akan memancarkan setiap baris di setiap file yang dicari, tetapi hanya kejadian foo yang akan disorot. Bendera ini memungkinkan perilaku yang sama tanpa perlu mengubah pola.

2
kenorb

Ada cara yang jauh lebih mudah untuk melakukan ini untuk GNU grep tapi saya tidak berpikir itu portabel (mis., BSD grep):

Dalam pipa:

cat <file> | grep --color=always -z <query>

Pada file:

grep --color=always -z <query> <file>

Kredit diberikan ke jawaban Cyrus di sini .

1
Erik Nomitch

Versi sed, dapat digunakan pada bash dan ash.

#highlight
hsed(){
    local pattern="$1"
    shift
    local r=`echo -e '\e'[31m`
    local c=`echo -e '\e'[0m`
    sed "s:${pattern//:/\:}:$r\0$c:g" "[email protected]"
}
0
yurenchen

OP meminta grep, dan itulah yang SAYA SARANKAN; tetapi setelah berusaha keras untuk memecahkan masalah dengan sed, sebagai catatan, berikut adalah solusi sederhana untuk itu:

sed $'s/main/\E[31m&\E[0m/g' testt.c

atau

cat testt.c | sed $'s/main/\E[31m&\E[0m/g'

Will Paint main dengan warna merah.

  • \E[31m: urutan mulai warna merah
  • \E[0m: tanda warna jadi
  • &: pola yang cocok
  • /g: semua kata dalam satu baris, bukan hanya yang pertama
  • $'string' adalah string bash dengan karakter yang lolos ditafsirkan

Mengenai grep, ia juga bekerja menggunakan ^ (mulai dari baris) alih-alih $ (ujung baris). Contoh:

egrep "^|main" testt.c

Dan hanya untuk menunjukkan alias gila ini itu SAYA TIDAK MEREKOMENDASIKAN, Anda bahkan dapat membiarkan tanda kutip terbuka:

alias h='egrep -e"^|'
h main" testt.c
cat testt.c | h main"

semua bekerja! :) Jangan khawatir jika Anda lupa untuk menutup kutipan, bash akan mengingat Anda dengan "karakter garis lanjutan".

0
Dr Beco