Saya harus membaca beberapa file JSON yang panjangnya melebihi beberapa ribu karakter. Bagaimana saya bisa membatasi grep untuk menampilkan konteks hingga N karakter di kiri dan kanan pertandingan? Alat apa pun selain grep juga akan baik-baik saja, asalkan tersedia dalam paket Linux umum.
Ini akan menjadi contoh output, untuk sakelar grep imajiner Ф :
$ grep -r foo *
hello.txt: Once upon a time a big foo came out of the woods.
$ grep -Ф 10 -r foo *
hello.txt: ime a big foo came of t
Jawaban:
Dengan GNU
grep
:Penjelasan:
-o
=> Cetak hanya apa yang Anda cocokkan-P
=> Gunakan ekspresi reguler Perl-style$N
karakter diikuti olehfoo
diikuti oleh 0 ke$N
karakter.Jika Anda tidak memiliki GNU
grep
:Penjelasan:
Karena kita tidak bisa lagi mengandalkan
grep
menjadi GNUgrep
, kami menggunakanfind
untuk mencari file secara rekursif (-r
tindakan GNUgrep
). Untuk setiap file yang ditemukan, kami menjalankan cuplikan Perl.Switch Perl:
-n
Baca file baris demi baris-l
Hapus baris baru di akhir setiap baris dan pasang kembali saat mencetak-e
Perlakukan string berikut sebagai kodeCuplikan Perl pada dasarnya melakukan hal yang sama dengan
grep
. Dimulai dengan mengatur variabel$N
ke jumlah karakter konteks yang Anda inginkan. TheBEGIN{}
sarana ini dijalankan hanya sekali pada awal eksekusi tidak sekali untuk setiap baris dalam setiap file.Pernyataan yang dieksekusi untuk setiap baris adalah untuk mencetak baris jika substitusi regex berfungsi.
Regex:
^.*?
) diikuti oleh.{0,$N}
seperti dalamgrep
kasus ini,foo
diikuti oleh yang lain.{0,$N}
dan akhirnya cocokkan barang lama dengan malas sampai akhir baris (.*?$
).$ARGV:$1
.$ARGV
adalah variabel magis yang menyimpan nama file saat ini sedang dibaca.$1
adalah apa yang cocok dengan orangtua: konteks dalam kasus ini.foo
tanpa gagal untuk mencocokkan (karena.{0,$N}
diizinkan untuk mencocokkan nol kali).1 Artinya, lebih memilih untuk tidak mencocokkan apa pun kecuali ini akan menyebabkan kecocokan keseluruhan gagal. Singkatnya, sesuaikan karakter sesedikit mungkin.
sumber
| grep foo
sampai akhir (namun kehilangan sorotan nama file dalam proses).grep
Anda dapat menentukan warna / aplikasi yang cocok berdasarkan flag yang diterapkan melalui variabel lingkungan. jadi mungkin bahkan Anda bisa memenangkan semuanya, (tidak ada janji - bahkan tidak yakin itu akan berhasil dalam kasus ini) tetapi saya pribadi tidak melihat relevansinya di sini ... tetap ... tetaplah bermain.zsh
saya tidak dapat membuatnya berfungsi melewati N = 10 seperti pada contoh. Namun itu berfungsi jika sayaexport N=10
sebelum menjalankan perintah. Adakah yang tahu bagaimana menyesuaikan contoh agar berfungsi dengan zsh?perl -lne 'print "$ARGV: $_" for /.{0,10}foo.{0,10}/g'
Coba gunakan yang ini:
-E memberi tahu, bahwa Anda ingin menggunakan regex diperpanjang
-o memberi tahu, bahwa Anda hanya ingin mencetak pertandingan
-r grep sedang mencari hasil secara rekursif di folder
REGEX:
{0,10} memberi tahu, berapa banyak karakter sewenang-wenang yang ingin Anda cetak
. mewakili karakter yang berubah-ubah (karakter itu sendiri tidak penting di sini, hanya nomor mereka)
Sunting: Oh, begitu, Joseph merekomendasikan solusi yang hampir sama dengan saya: D
sumber
-E
secara signifikan lebih cepat daripada-P
.Diambil dari: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/ dan https: // stackoverflow. com / a / 39029954/1150462
Pendekatan yang disarankan
".{0,10}<original pattern>.{0,10}"
sangat baik kecuali untuk itu warna highlight sering kacau. Saya telah membuat skrip dengan output serupa tetapi warnanya juga dipertahankan:Dengan asumsi skrip disimpan sebagai
grepl
, makagrepl pattern file_with_long_lines
harus menampilkan garis yang cocok tetapi dengan hanya 10 karakter di sekitar string yang cocok.sumber
Stdout perpipaan
cut
dengan-b
bendera; Anda dapat menginstruksikan output grep hanya byte 1 hingga 400 per baris.sumber