grep untuk mengembalikan garis Nth dan Mth sebelum dan sesudah pertandingan

12

Saya tahu bahwa dengan grep saya dapat menggunakan bidang -Adan -Buntuk menarik garis sebelumnya dan berikutnya dari pertandingan.

Namun mereka menarik semua garis di antara pertandingan berdasarkan berapa banyak baris yang ditentukan.

grep -r -i -B 5 -A 5 "match" 

Saya hanya ingin menerima baris ke- 5 sebelum pertandingan dan baris ke- 5 setelah pertandingan selain garis yang cocok dan tidak mendapatkan garis di antara keduanya.

Apakah ada cara untuk melakukan ini dengan grep?

chollida
sumber
1
Anda bisa melakukannya dengan menyalurkannya ke sed. Saya baru saja menguji ini dan itu berhasil, tetapi hanya berhasil ketika ada 1 pencocokan tepat dalam file: grep -r -i -B 5 -A 5 "match" | sed -e 1b -e '$!d'
Terrance
@Terrance terima kasih atas sarannya, seperti yang Anda sebutkan, karena saya mengumpulkan 1000-an baris, ini tidak akan berhasil.
chollida
Saya tidak berpikir grep akan bekerja dengan sendirinya ... Saya sedang mengerjakan skrip bash untuk Anda
Joshua Besneatte
Tidak masalah! Agak tertarik melihat jawaban apa yang Anda dapatkan. =)
Terrance
Apakah ini dalam satu file atau beberapa file?
Joshua Besneatte

Jawaban:

1

Alat yang ingin Anda gunakan disebut sift. Ini pada dasarnya grep pada steroid. Grep secara paralel. Sift memiliki sejumlah besar opsi untuk melakukan apa yang Anda inginkan - khususnya untuk mengembalikan garis tertentu relatif terhadap kecocokan yang mungkin / mungkin tidak diikuti / didahului oleh beberapa teks.

Sungguh mengherankan saya bahwa menyaring bukan arus utama gnu seperti yang ditulis dalam bahasa go tetapi menginstal di Linux baik-baik saja. Pencarian IT secara paralel menggunakan semua teks dalam jumlah besar di mana grep hanya membutuhkan waktu berminggu-minggu untuk melakukan hal yang sama.

Ayak situs web - lihat contoh

Brandon Haberfeld
sumber
Selamat datang di AskUbuntu, terima kasih telah menjawab. Anda perlu memberikan contoh CLI yang dapat memecahkan masalah khusus ini daripada memberikan tautan ke situs web sift. Ini adalah T&J, terima kasih.
Bernard Wei
12

Jika:

cat file
a
b
c
d
e
f match
g
h
i match
j
k
l
m
n
o

Kemudian:

awk '
    {line[NR] = $0} 
    /match/ {matched[NR]} 
    END {
        for (nr in matched)
            for (n=nr-5; n<=nr+5; n+=5) 
                print line[n]
    }
' file
a
f match
k
d
i match
n
glenn jackman
sumber
+1, tetapi bisakah Anda menjelaskan semantiknya /match/ {matched[NR]}? Saya belum pernah melihat array atau variabel sebagai keseluruhan perintah. Apakah itu menempatkan nomor catatan saat ini dari setiap baris yang cocok ke dalam array.
Joe
Ini adalah keanehan awk: jika Anda mereferensikan elemen array tanpa penugasan, kunci itu ditambahkan ke array (tanpa nilai). Kemudian kunci itu muncul di ekspresi key in array. Apa yang saya lakukan adalah mengingat nomor baris di mana polanya muncul
glenn jackman
6

Ini pada dasarnya adalah solusi Glenn, tetapi diimplementasikan dengan Bash, Grep, dan sed.

grep -n match file |
    while IFS=: read nr _; do
        sed -ns "$((nr-5))p; $((nr))p; $((nr+5))p" file
    done

Perhatikan bahwa nomor baris kurang dari 1 akan membuat kesalahan sed, dan nomor baris lebih besar dari jumlah baris dalam file tidak akan mencetak apa pun.

Ini hanya minimum. Untuk membuatnya bekerja secara rekursif dan menangani kasus-kasus nomor baris di atas akan membutuhkan beberapa pekerjaan.

wjandrea
sumber
6

Itu tidak bisa dilakukan hanya dengan grep. Jika edopsi:

ed -s file << 'EOF' 
g/match/-5p\
+5p\
+5p
EOF  

Script pada dasarnya mengatakan: untuk setiap kecocokan / cocok /, cetak baris 5 baris sebelum itu, lalu 5 baris setelah itu, lalu 5 baris setelah itu.

JoL
sumber
5
@ubashu Apakah Anda pikir akan lebih membantu OP memberikan flat sederhana "tidak dapat dilakukan dengan grep"? Saya memberikan apa yang saya yakini sebagai alternatif yang baik untuk menyelesaikan masalah OP. Dari Pusat Bantuan: "Apa, khususnya, pertanyaan yang diajukan? Pastikan jawaban Anda memberikan itu - atau alternatif yang layak. Jawabannya bisa 'jangan lakukan itu', tetapi itu juga harus mencakup 'coba ini' . "
JoL
edadalah selalu jawaban, karena edadalah editor teks standar.
hidangan penutup
5
@ubashu Meskipun ini bukan grepjawaban, jawaban "Anda tidak dapat melakukannya dengan X, tetapi Anda dapat melakukannya dengan Y, begini caranya" masih merupakan jawaban yang valid karena Anda tidak hanya menjawab pertanyaan OP tetapi Anda juga memberikan alternatif itu akan berhasil. Ini adalah jenis jawaban yang valid di sini.
Thomas Ward
5
awk '/match/{system("sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME)}' infile

Di sini kita menggunakan awk 's fungsi untuk memanggil eksternal perintah untuk mencetak garis yang awk cocok dengan pola dengan 5 th baris sebelum dan setelah pertandingan.system(command)sedmatch

Sintaksnya mudah, Anda hanya perlu menempatkan perintah eksternal itu sendiri di dalam tanda kutip ganda serta sakelar-sakelarnya dan melepaskan diri dari hal-hal yang Anda inginkan, secara persis lolos ke perintah, semua yang terkait dengan awkopsi itu sendiri harus berada di luar tanda kutip. Jadi sed di bawah ini :

"sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME

Terjemahkan ke:

sed -n "NR-5p; NRp; NR+5p" FILENAME

NRadalah nomor baris yang cocok dengan pola matchdan FILENAMEmerupakan nama pemrosesan saat ini yang lewat awk.

αғsнιη
sumber
2

menggunakan file teks contoh @ glenn dan menggunakan perl bukan awk:

$ perl -n0E 'say /(.*\n)(?=(?:.*\n){4}(.*match.*\n)(?:.*\n){4}(.*\n))/g' ex

akan memberikan hasil yang sama, tetapi berjalan lebih cepat:

a
f match
k
d
i match
n
Fabby
sumber
João, Anda muncul di antrean ulasan LQ dan @waltinator memilih untuk menghapus, jadi lain kali lebih sedikit bertele-tele ... ;-) Juga memberi +1 untuk mengeluarkan Anda dari antrian LQ ... : P
Fabby
1
@JJoao Antrian ulasan berkualitas rendah. Jawaban Anda mungkin dijemput di sana karena 90% kode.
wjandrea
1
@ Jojo Angka 90% hanya cara saya menjelaskannya. Saya tidak tahu heuristik apa yang sebenarnya digunakan.
wjandrea
1
Menos café, mais escrita! @ Jojo : D ;-): D
Fabby
1
@Fabby: Sem café nada funciona: D - mungkin itu akan muncul di LCQ (= antrian kopi rendah)