Làm thế nào để chỉ hiển thị dòng tiếp theo sau khi phù hợp?


218
grep -A1 'blah' logfile

Nhờ lệnh này cho mọi dòng có 'blah' trong đó, tôi có được đầu ra của dòng chứa 'blah' và dòng tiếp theo trong logfile. Nó có thể là một cách đơn giản nhưng tôi không thể tìm cách bỏ qua dòng có 'blah' và chỉ hiển thị dòng tiếp theo trong đầu ra.


71
Tôi nghĩ rằng nhiều người sẽ đến đây để tìm kiếm -A1lựa chọn
mirelon

Sau đó, tôi sử dụng điều này để có được IP công cộng của tôi. :)curl whatismyip.org | grep -A1 'Your IP Address'
shrekuu 18/07/2015

6
Tương tự -B1, -B2, -B3, -A1, -A2, -A3. . .
meawoppl

5
@shrek curl icanhazip.com (không cần grep) :)
alexyorke

1
Bạn câu hỏi đã trả lời câu hỏi của tôi ... -A1. Cảm ơn!
S3DEV

Câu trả lời:


181

bạn có thể thử với awk:

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

3
Đối với bất kỳ ai thực sự muốn có một grep -A2 tương đương (đó là những gì tôi cần), getline chỉ cần ăn dòng và đi tiếp theo. Vì vậy, những gì làm việc cho tôi theo nghĩa đen chỉ làawk '/blah/{getline; getline; print}' logfile
Aaron R.

160

nếu bạn muốn dính vào grep:

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

hoặc là

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

2
@Kent, cảm ơn vì tiền boa. Từ POV của tôi, grep dễ đọc và dễ nắm bắt hơn nhiều so với sed hoặc câu trả lời awk được đánh dấu là câu trả lời hay nhất .... nhưng đó chỉ là tôi có thể :)
icasimpan

2
Đối với những người tò mò về những gì -v làm: -v --invert-match Đảo ngược ý nghĩa của kết hợp, để chọn các dòng không khớp. (-v được chỉ định bởi POSIX.)
Sammi

2
Tôi thực sự thích câu trả lời này, nhưng nó sẽ không hoạt động nếu bạn có hai dòng liên tiếp chứa "blah" và muốn lấy câu thứ hai (vì đó là "dòng tiếp theo sau dòng trùng khớp"). Tôi không thể nghĩ ra bất kỳ trường hợp sử dụng nào cho điều đó ra khỏi đầu, nhưng nó đáng chú ý.
Tin phù thủy

Giải pháp hàng đầu chỉ đơn giản là "ok". Nếu dòng thứ hai cũng có "blah" trong đó, bạn sẽ có một mớ hỗn độn thực sự trên tay.
riwalk

32

Piping là bạn của bạn ...

Sử dụng grep -A1để hiển thị dòng tiếp theo sau một trận đấu, sau đó dẫn kết quả đến tailvà chỉ lấy 1 dòng,

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

1
Nếu "hạn" nằm ở dòng cuối cùng, điều này sẽ trả về dòng chứa "hạn" thay vì không có gì, bạn muốn gì.
Onnonymous

đuôi -n 1 sẽ chỉ dẫn đến dòng cuối cùng của toàn bộ tệp
Sebastian

13

Câu trả lời tuyệt vời từ raim, rất hữu ích cho tôi. Việc mở rộng này để in, ví dụ như dòng 7 sau mẫu

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

9

Nếu dòng tiếp theo không bao giờ chứa 'blah', bạn có thể lọc chúng bằng:

grep -A1 blah logfile | grep -v blah

Việc sử dụng cat logfile | ...là không cần thiết.


5

Nói chung, tôi đồng ý rằng bạn đang hỏi rất nhiều grep ở đây và rằng một công cụ khác có thể là giải pháp tốt hơn. Nhưng trong một môi trường nhúng, tôi có thể không muốn sedhoặc awkchỉ để làm điều này. Tôi đã tìm thấy giải pháp sau đây hoạt động (miễn là chúng không khớp nhau):

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

Về cơ bản, khớp chúng, nối thêm 1 dòng ngữ cảnh cho mỗi trận đấu và sau đó chuyển qua một trận đấu nghịch đảo của mẫu ban đầu của bạn để loại bỏ chúng. Tất nhiên điều này có nghĩa là bạn có thể cho rằng mẫu của bạn không hiển thị trong dòng "tiếp theo".


5

Nhiều câu trả lời tốt đã được đưa ra cho câu hỏi này cho đến nay, nhưng tôi vẫn bỏ lỡ một câu awkkhông sử dụng getline. Vì, nói chung , không cần thiết phải sử dụng getline, tôi sẽ đi:

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

hoặc là

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

Logic luôn bao gồm việc lưu trữ dòng nơi "blah" được tìm thấy và sau đó in những dòng đó là một dòng sau đó.

Kiểm tra

Tệp mẫu:

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

Nhận tất cả các dòng sau "blah". Cái này in một chữ "blah" khác nếu nó xuất hiện sau cái đầu tiên.

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

Nhận tất cả các dòng sau "blah" nếu chúng không chứa "blah".

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

5

Tôi không biết cách nào để làm điều này với grep, nhưng có thể sử dụng awk để đạt được kết quả tương tự:

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

@jww Không có gì khác biệt. Như bạn có thể thấy từ các dấu thời gian chỉ cách nhau vài phút, có vẻ như tôi đã trả lời cùng một lúc.
raimue

4

cảnh báo một lớp lót

chỉ để giải trí ... chỉ in một dòng sau trận đấu

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

thậm chí còn vui hơn ... in mười dòng tiếp theo sau trận đấu

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

Mặc dù gian lận vì thực tế có hai lệnh


Bạn có thể giải thích $. == $ tiếp theo không? Rõ ràng nó không chỉ là so sánh số của số dòng hiện tại với $ next, nhưng tôi không hiểu cách thức / lý do tại sao nó hoạt động.
Keith Bentrup

Nó không hơn thế. $. == $next && printgiống nhưprint if $. == $next
beasy

À, tôi hiểu rồi. Cám ơn! Trong số 2 phần, mỗi phần là đúng và thực hiện trên các lần lặp riêng biệt, liền kề của vòng lặp. Tôi cho rằng nếu điểm là in bất kỳ dòng nào sau bất kỳ trận đấu nào mà bạn muốn đảo ngược thứ tự (sẽ hành xử giống như vậy hơn grep -A1). Nếu bạn chỉ muốn in các dòng tiếp theo nhưng không bao giờ là một dòng có khớp, thì bạn sẽ giữ nó theo thứ tự này. (chỉ lưu ý cách $ tiếp theo sẽ bị ghi đè cho các trận đấu liên tiếp)
Keith Bentrup

3

Có vẻ như bạn đang sử dụng công cụ sai ở đó. Grep không tinh vi đến thế, tôi nghĩ bạn muốn bước lên để trở thành công cụ cho công việc:

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

Nếu bạn gặp bất kỳ vấn đề nào hãy cho tôi biết, tôi nghĩ nó cũng đáng để học hỏi một chút, đó là một công cụ tuyệt vời :)

ps Ví dụ này không giành được giải thưởng 'việc sử dụng mèo vô dụng';) http://porkmail.org/era/unix/award.html


3
BTW, bạn có thể bỏ qua "$ 0" trong bản in.
Michał Šrajer

0

grep / Mẫu / | đuôi -n 2 | đầu -n 1

Đuôi 2 đầu tiên và sau đó đi đến cuối cùng để có được dòng đầu tiên chính xác sau trận đấu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.