Bagaimana cara menampilkan baris berikutnya setelah yang cocok?

218
grep -A1 'blah' logfile

Berkat perintah ini untuk setiap baris yang memiliki 'bla' di dalamnya, saya mendapatkan output dari baris yang berisi 'bla' dan baris berikutnya yang mengikuti di logfile. Mungkin yang sederhana tapi saya tidak bisa menemukan cara untuk menghilangkan baris yang memiliki 'bla' dan hanya menampilkan baris berikutnya di output.

facha
sumber
71
Saya pikir banyak orang akan datang ke sini mencari -A1opsi
mirelon
Lalu saya menggunakan ini untuk mendapatkan IP publik saya. :)curl whatismyip.org | grep -A1 'Your IP Address'
shrekuu
6
Demikian pula -B1, -B2, -B3, -A1, -A2, -A3. . .
meawoppl
5
@shrek curl icanhazip.com (tidak perlu grep) :)
alexyorke
1
Anda pertanyaan menjawab pertanyaan saya ... -A1. Terima kasih!
S3DEV

Jawaban:

181

Anda dapat mencoba dengan awk:

awk '/blah/{getline; print}' logfile
Michał Šrajer
sumber
3
Bagi siapa pun yang benar-benar menginginkan grep -A2 yang setara (yang saya butuhkan), getline hanya makan garis dan melanjutkan ke yang berikutnya. Jadi apa yang berhasil bagi saya benar-benar adilawk '/blah/{getline; getline; print}' logfile
Aaron R.
160

jika Anda ingin tetap berpegang pada grep:

grep -A1 'blah' logfile|grep -v "blah"

atau

sed -n '/blah/{n;p;}' logfile
Kent
sumber
2
@ Kent, terima kasih atas tipnya. Dari POV saya, grep jauh lebih mudah dibaca dan mudah dipahami dibandingkan dengan sed atau jawaban awk ditandai sebagai jawaban terbaik .... tapi itu hanya saya mungkin :)
icasimpan
2
Bagi mereka yang penasaran dengan apa yang dilakukan v: -v --invert-match Balikkan indra pencocokan, untuk memilih jalur yang tidak cocok. (-v ditentukan oleh POSIX.)
Sammi
2
Saya sangat suka jawaban ini, tetapi itu tidak akan berhasil jika Anda memiliki dua baris berturut-turut yang berisi "bla" dan ingin mendapatkan yang kedua (karena "baris berikutnya setelah yang cocok"). Saya tidak bisa memikirkan kasus penggunaan apa pun yang ada di luar kepala saya, tetapi perlu dicatat.
Tin Wizard
Solusi teratas hanyalah "ok". Jika baris kedua kebetulan memiliki "bla" di dalamnya, Anda akan benar-benar berantakan.
riwalk
32

Piping adalah temanmu ...

Gunakan grep -A1untuk menunjukkan baris berikutnya setelah pertandingan, lalu kirimkan hasilnya ke taildan hanya ambil 1 baris,

cat logs/info.log | grep "term" -A1 | tail -n 1
weisjohn
sumber
1
Jika "term" berada di baris terakhir, ini akan mengembalikan baris yang mengandung "term", bukan apa-apa, yang Anda inginkan.
Onnonymous
tail -n 1 hanya akan menghasilkan baris terakhir dari seluruh file
Sebastian
13

Jawaban yang bagus dari raim, sangat berguna bagi saya. Sangat sepele untuk memperluas ini untuk mencetak misalnya garis 7 setelah pola

awk -v lines=7 '/blah/ {for(i=lines;i;--i)getline; print $0 }' logfile
souter
sumber
9

Jika baris berikutnya tidak pernah berisi 'bla', Anda dapat memfilternya dengan:

grep -A1 blah logfile | grep -v blah

Penggunaan cat logfile | ...tidak diperlukan.

ott--
sumber
5

Secara umum, saya setuju Anda meminta banyak grep di sini, dan bahwa alat lain mungkin solusi yang lebih baik. Tetapi dalam lingkungan yang tertanam, saya mungkin tidak ingin sedatau awkhanya melakukan ini. Saya menemukan solusi berikut ini berfungsi (asalkan tidak cocok secara bersamaan):

grep -A1 AT\+CSQ wvdial.out | grep -v AT\+CSQ

Pada dasarnya, cocokkan mereka, tambahkan 1 baris konteks untuk setiap pertandingan, dan kemudian pipa itu melalui kecocokan terbalik dari pola asli Anda untuk menghapusnya. Ini tentu saja berarti Anda dapat mengasumsikan bahwa pola Anda tidak muncul di baris "berikutnya".

Travis Griggs
sumber
5

Banyak jawaban baik telah diberikan untuk pertanyaan ini sejauh ini, tetapi saya masih merindukannya dengan awktidak menggunakan getline. Karena, secara umum , tidak perlu digunakan getline, saya akan menggunakan:

awk ' f && NR==f+1; /blah/ {f=NR}' file  #all matches after "blah"

atau

awk '/blah/ {f=NR} f && NR==f+1' file   #matches after "blah" not being also "blah"

Logikanya selalu terdiri dari menyimpan garis di mana "bla" ditemukan dan kemudian mencetak garis-garis yang satu baris setelahnya.

Uji

File sampel:

$ cat a
0
blah1
1
2
3
blah2
4
5
6
blah3
blah4
7

Dapatkan semua kalimat setelah "bla". Ini mencetak "bla" lain jika muncul setelah yang pertama.

$ awk 'f&&NR==f+1; /blah/ {f=NR}' a
1
4
blah4
7

Dapatkan semua baris setelah "bla" jika tidak mengandung "bla" sendiri.

$ awk '/blah/ {f=NR} f && NR==f+1' a
1
4
7
fedorqui 'SO berhenti merugikan'
sumber
5

Saya tidak tahu cara untuk melakukan ini dengan grep, tetapi dimungkinkan untuk menggunakan awk untuk mencapai hasil yang sama:

awk '/blah/ {getline;print}' < logfile
raimue
sumber
@jww Tidak ada perbedaan. Seperti yang dapat Anda lihat dari cap waktu yang hanya berjarak beberapa menit, tampaknya saya menjawab sekitar waktu yang sama.
raimue
4

perl satu peringatan liner

hanya untuk bersenang-senang ... hanya mencetak satu baris setelah pertandingan

perl -lne '$next=($.+1)if/match/;$.==$next&&print' data.txt

bahkan lebih menyenangkan ... cetak sepuluh baris berikutnya setelah pertandingan

perl -lne 'push@nexts,(($.+1)..($.+10))if/match/;$.~~@nexts&&print' data.txt

agak curang karena sebenarnya ada dua perintah

beasy
sumber
Bisakah Anda jelaskan $. == $ berikutnya? Jelas itu lebih dari perbandingan numerik dari nomor baris saat ini dengan $ next, tapi saya tidak mengerti bagaimana / mengapa ia bekerja.
Keith Bentrup
Tidak lebih dari itu. $. == $next && printsama denganprint if $. == $next
beasy
Ah, saya mengerti sekarang. Terima kasih! Dari 2 bagian, masing-masing adalah benar dan dijalankan pada iterasi yang terpisah dan berdekatan dari loop. Saya kira jika intinya adalah mencetak garis apa pun setelah kecocokan apa pun yang Anda ingin membalikkan urutan (akan berperilaku lebih seperti grep -A1). Jika Anda ingin mencetak hanya baris berikutnya tetapi tidak pernah baris dengan korek api, maka Anda akan tetap memesan ini. (Hanya mencatat bagaimana $ berikutnya akan musnah untuk pertandingan berturut-turut)
Keith Bentrup
3

Sepertinya Anda menggunakan alat yang salah di sana. Grep tidak secanggih itu, saya pikir Anda ingin menjadi awk sebagai alat untuk pekerjaan itu:

awk '/blah/ { getline; print $0 }' logfile

Jika Anda mendapatkan masalah, beri tahu saya, saya pikir perlu belajar sedikit awk, ini alat yang hebat :)

ps Contoh ini tidak memenangkan 'penggunaan kucing yang tidak berguna';) http://porkmail.org/era/unix/award.html

konyol konyol
sumber
3
BTW, Anda dapat melewati "$ 0" dalam bentuk cetak.
Michał Šrajer
0

grep / Pola / | tail -n 2 | kepala -n 1

Buntut yang pertama 2 dan kemudian yang terakhir untuk mendapatkan garis pertama yang tepat setelah pertandingan.

Amrit Pal Singh
sumber