Eşleştikten sonra yalnızca bir sonraki satırı nasıl gösterebilirim?


218
grep -A1 'blah' logfile

İçinde 'blah' olan her satır için bu komut sayesinde, 'blah' içeren satırın çıktısını ve günlük dosyasında izleyen bir sonraki satırı alıyorum. Basit olabilir ama 'falan' olan satırı atlamanın ve çıktıda sadece bir sonraki satırı göstermenin bir yolunu bulamıyorum .


72
Sanırım birçok kişi buraya -A1seçeneği arıyor
mirelon

Sonra bunu genel IP adresimi almak için kullanıyorum. :)curl whatismyip.org | grep -A1 'Your IP Address'
shrekuu

6
Benzer şekilde -B1, -B2, -B3, -A1, -A2, -A3. . .
meawoppl

5
@shrek bukle icanhazip.com :) (hayır grep gerekli)
alexyorke

1
Sorunuz sorumu yanıtladı -A1. Teşekkürler!
S3DEV

Yanıtlar:


181

awk ile deneyebilirsiniz:

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

3
Gerçekten bir grep -A2 eşdeğeri (ihtiyaç duyduğum şey) isteyen herkes için, getline sadece hattı yiyor ve bir sonrakine gidiyor. Benim için işe awk '/blah/{getline; getline; print}' logfile
Aaron R.

160

grep'e sadık kalmak istiyorsanız:

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

veya

sed -n '/blah/{n;p;}' logfile

2
@Kent, bahşiş için teşekkürler. Benim POV olsa da, grep sed ya da en iyi cevap olarak işaretlenmiş awk cevap karşılaştırıldığında çok daha okunabilir ve kavramak kolaydır .... ama bu sadece ben belki :)
icasimpan

2
-V'nin ne yaptığını merak edenler için: -v --invert-match Eşleşmeyen duyguyu ters çevirin, eşleşmeyen satırları seçin. (-v, POSIX tarafından belirtilir.)
Sammi

2
Bu yanıtı gerçekten seviyorum, ancak "blah" içeren bir satırda iki satırınız varsa ve ikincisini almak istiyorsanız işe yaramaz (çünkü "eşleşen satırdan sonraki satır"). Bunun için herhangi bir kullanım durumu düşünemiyorum, ama kayda değer.
Tin Wizard

En iyi çözüm sadece "tamam" dır. İkinci satırda da "falan" varsa, ellerinde gerçek bir karışıklık olur.
riwalk

32

Boru hattı senin arkadaşın ...

grep -A1Bir maçtan sonra bir sonraki satırı göstermek için kullanın , ardından sonucu boruya tailekleyin ve yalnızca 1 satıra alın,

cat logs/info.log | grep "term" -A1 | tail -n 1

1
Eğer "terim" son satırdaysa, bu hiçbir şey yerine "terim" içeren satırı geri döndürür.
Onnonymous

kuyruk -n 1 sadece tüm dosyanın son satırını verecektir
Sebastian

13

Raimden gelen büyük cevap, benim için çok yararlı oldu. Bunu, örneğin kalıptan sonra 7 numaralı satırı yazdırmak için uzatmak önemsizdir

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

9

Sonraki satırlarda hiçbir zaman 'filan' yoksa, bunlara filtre uygulayabilirsiniz:

grep -A1 blah logfile | grep -v blah

Kullanımı cat logfile | ...gerekli değildir.


5

Genel olarak, burada çok fazla grep istediğini ve başka bir aracın daha iyi bir çözüm olabileceğini kabul ediyorum. Ancak gömülü bir ortamda, bunu yapmak istemeyebilir sedveya awksadece bunu yapmak isteyebilirim . Aşağıdaki çözüm çalışmalarını buldum (bitişik eşleşmeler olmadığı sürece):

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

Temel olarak, onları eşleştirin, her eşleşme için 1 satır bağlam ekleyin ve ardından bunları orijinal kalıbınızın ters eşleşmesinden geçirin. Bu, elbette, deseninizin "sonraki" satırında görünmediğini varsayabileceğiniz anlamına gelir.


5

Şimdiye kadar bu soruya çok iyi cevaplar verildi, ancak hala awkkullanmamakla bir tane özlüyorum getline. Yana genel olarak , kullanmak için gerekli değildir getline, ben giderdim:

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

veya

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

Mantık her zaman "falan" ın bulunduğu satırı saklamak ve sonra bir satır sonra olan satırları yazdırmaktan ibarettir.

Ölçek

Örnek dosya:

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

"Blah" dan sonra tüm satırları alın. İlkinden sonra görünüyorsa, bu başka bir "falan" basar.

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

Eğer "blah" içermiyorlarsa "blah" dan sonra tüm satırları alın.

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

5

Bunu grep ile yapmanın hiçbir yolunu bilmiyorum, ancak aynı sonucu elde etmek için awk kullanmak mümkündür:

awk '/blah/ {getline;print}' < logfile

@jww Fark yok. Sadece birkaç dakika uzaklıktaki zaman damgalarından görebileceğiniz gibi, aynı zamanda cevapladığım anlaşılıyor.
raimue

4

perl tek astar uyarısı

sadece eğlence için ... maçtan sonra sadece bir satır yazdır

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

daha da eğlenceli ... maçtan sonraki on satırı yazdır

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

aslında iki komut olduğu için hile yapmak


Şimdi $. == $ açıklayabilir misiniz? Açıkçası, mevcut satır numarasının $ next ile sayısal bir karşılaştırmasından daha fazlası, ancak nasıl / neden çalıştığını anlamıyorum.
Keith Bentrup

Bundan daha fazlası değil. $. == $next && printaynıprint if $. == $next
beasy

Ah, şimdi görüyorum. Teşekkürler! 2 bölümden her biri doğrudur ve döngünün ayrı, bitişik yinelemelerinde yürütülür. Sanırım nokta, siparişi tersine çevirmek istediğiniz herhangi bir eşleşmeden sonra herhangi bir satır yazdırmaksa (daha çok davranırdı grep -A1). Yalnızca sonraki satırları yazdırmak, ancak asla eşleşmeyen bir satır yazdırmak istiyorsanız, bu sırayı koruyacaksınız. (sıradaki maçlar için bir sonraki $ 'ın nasıl tıkanacağına dikkat çekerek)
Keith Bentrup

3

Görünüşe göre orada yanlış aracı kullanıyorsunuz. Grep o kadar sofistike değil, bence işin aracı olarak awk yapmak için adım atmak istiyorsunuz:

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

Herhangi bir sorun varsa bana bildirin, bence biraz awk öğrenmeye değer, harika bir araç :)

ps Bu örnek 'yararsız kedi kullanımı ödülü' kazanmaz;) http://porkmail.org/era/unix/award.html


3
BTW, "$ 0" yazısını atlayabilirsiniz.
Michał Šrajer

0

grep / Desen / | kuyruk -n 2 | kafa -n 1

İlk 2'yi kuyruklayın ve ardından maçtan sonra tam olarak ilk satırı almak için sonuncusuna gidin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.