จะแสดงเฉพาะบรรทัดถัดไปหลังจากจับคู่ได้อย่างไร


218
grep -A1 'blah' logfile

ขอบคุณคำสั่งนี้สำหรับทุกบรรทัดที่มี 'blah' อยู่ในนั้นฉันได้รับเอาต์พุตของบรรทัดที่มี 'blah' และบรรทัดถัดไปที่ตามมาใน logfile อาจเป็นวิธีที่ง่าย แต่ฉันไม่สามารถหาวิธีเว้นบรรทัดที่มี 'blah' และแสดงเฉพาะบรรทัดถัดไปในผลลัพธ์ได้


72
ฉันคิดว่าหลายคนจะมาที่นี่เพื่อค้นหา-A1ตัวเลือก
mirelon

จากนั้นฉันใช้สิ่งนี้เพื่อรับ IP สาธารณะของฉัน :)curl whatismyip.org | grep -A1 'Your IP Address'
shrekuu

6
ในทำนองเดียวกัน -B1, -B2, -B3, -A1, -A2, -A3 . .
meawoppl

5
@shrek curl icanhazip.com (ไม่จำเป็นต้องใช้ grep) :)
alexyorke

1
คุณคำถามตอบคำถามของฉัน -A1... ขอบคุณ!
S3DEV

คำตอบ:


181

คุณสามารถลองด้วย awk:

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

3
สำหรับผู้ที่ต้องการ grep -A2 จริง ๆ (ซึ่งเป็นสิ่งที่ฉันต้องการ), getline แค่กินบรรทัดและไปต่อไป ดังนั้นสิ่งที่ใช้ได้ผลกับฉันก็คือawk '/blah/{getline; getline; print}' logfile
อาร์อาร์อาร์

160

ถ้าคุณต้องการที่จะ grep:

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

หรือ

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

2
@ เคนขอบคุณสำหรับเคล็ดลับ จากมุมมองของฉันแม้ว่า grep สามารถอ่านได้มากขึ้นและง่ายต่อการเข้าใจเมื่อเทียบกับ sed หรือคำตอบ awk ที่มีเครื่องหมายเป็นคำตอบที่ดีที่สุด .... แต่มันเป็นเพียงฉันอาจ :)
icasimpan

2
สำหรับผู้ที่อยากรู้อยากเห็นเกี่ยวกับสิ่งที่ -v ทำ: -v - กลับการจับคู่สลับความรู้สึกของการจับคู่เพื่อเลือกเส้นที่ไม่ตรงกัน (-v ถูกระบุโดย POSIX)
Sammi

2
ฉันชอบคำตอบนี้จริง ๆ แต่มันจะไม่ทำงานถ้าคุณมีสองบรรทัดในแถวที่มี "blah" และต้องการรับบรรทัดที่สอง (เพราะเป็น "บรรทัดถัดไปหลังจากที่ตรงกัน") ฉันไม่สามารถนึกถึงกรณีการใช้งานใด ๆ สำหรับสิ่งนั้นที่อยู่ด้านบนของหัวของฉัน แต่มันก็คุ้มค่าที่จะสังเกต
Tin Wizard

ทางออกที่ดีที่สุดคือ "ตกลง" เท่านั้น หากบรรทัดที่สองมี "blah" อยู่ด้วยเช่นกันคุณจะมีความยุ่งเหยิงในมือของคุณ
riwalk

32

ท่อเป็นเพื่อนของคุณ ...

ใช้grep -A1เพื่อแสดงบรรทัดถัดไปหลังจากการแข่งขันจากนั้นไปที่ผลลัพธ์tailและคว้าเพียง 1 บรรทัด

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

1
หาก "term" อยู่บนบรรทัดสุดท้ายนี่จะส่งคืนบรรทัดที่มีคำว่า "term" แทนสิ่งใดสิ่งที่คุณต้องการ
Onnonymous

tail -n 1 จะส่งผลให้บรรทัดสุดท้ายของไฟล์ทั้งหมด
Sebastian

13

คำตอบที่ดีจากไรมอนมีประโยชน์มากสำหรับฉัน มันไม่สำคัญที่จะขยายสิ่งนี้เพื่อพิมพ์เช่นบรรทัด 7 หลังจากรูปแบบ

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

9

หากบรรทัดถัดไปนั้นไม่มี 'blah' คุณสามารถกรองได้ด้วย:

grep -A1 blah logfile | grep -v blah

การใช้cat logfile | ...ไม่จำเป็นต้อง


5

โดยทั่วไปฉันยอมรับว่าคุณกำลังขอ grep จำนวนมากที่นี่และเครื่องมืออื่นอาจเป็นทางออกที่ดีกว่า แต่ในสภาพแวดล้อมแบบฝังตัวฉันอาจไม่ต้องการsedหรือawkทำสิ่งนี้ ฉันพบวิธีแก้ปัญหาต่อไปนี้ใช้งานได้ (ตราบใดที่มันไม่ตรงกันอย่างต่อเนื่อง):

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

โดยพื้นฐานแล้วจับคู่ต่อท้ายบริบท 1 บรรทัดสำหรับแต่ละการแข่งขันแล้วไปป์ที่ผ่านการจับคู่แบบผกผันของรูปแบบดั้งเดิมของคุณเพื่อตัดออก หลักสูตรนี้หมายความว่าคุณสามารถสมมติว่ารูปแบบของคุณไม่ปรากฏในบรรทัด "ถัดไป"


5

คำตอบที่ดีหลายคนได้รับคำถามนี้เพื่อให้ห่างไกล แต่ฉันยังคงคิดถึงหนึ่งที่มีไม่ได้ใช้awk getlineเนื่องจากโดยทั่วไปแล้วไม่จำเป็นต้องใช้getlineฉันจะไปเพื่อ:

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

หรือ

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

ตรรกะประกอบด้วยการจัดเก็บบรรทัดที่พบ "blah" เสมอแล้วพิมพ์บรรทัดเหล่านั้นที่เป็นหนึ่งบรรทัดหลังจาก

ทดสอบ

ไฟล์ตัวอย่าง:

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

รับทุกบรรทัดหลังจาก "blah" สิ่งนี้จะพิมพ์ "blah" อีกอันถ้ามันปรากฏขึ้นหลังจากอันแรก

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

รับทุกบรรทัดหลังจาก "blah" หากพวกเขาไม่มี "blah" ด้วยตนเอง

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

5

ฉันไม่รู้วิธีการทำเช่นนี้กับ grep แต่เป็นไปได้ที่จะใช้ awk เพื่อให้ได้ผลลัพธ์เดียวกัน:

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

@ jww ไม่มีความแตกต่าง อย่างที่คุณเห็นจากการประทับเวลาที่ห่างกันเพียงไม่กี่นาทีก็ปรากฏว่าฉันตอบไปในเวลาเดียวกัน
เครื่องใช้

4

perl หนึ่งซับการแจ้งเตือน

เพียงเพื่อความสนุก ... พิมพ์เพียงหนึ่งบรรทัดหลังการแข่งขัน

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

สนุกยิ่งขึ้น ... พิมพ์สิบบรรทัดถัดไปหลังจากการแข่งขัน

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

ค่อนข้างจะโกงเนื่องจากมีสองคำสั่งจริง


คุณช่วยอธิบาย $. == $ ต่อไปได้ไหม เห็นได้ชัดว่ามันเป็นมากกว่าการเปรียบเทียบตัวเลขของหมายเลขบรรทัดปัจจุบันด้วย $ ถัดไป แต่ฉันไม่เข้าใจว่ามันทำงานอย่างไร
Keith Bentrup

ไม่มากไปกว่านั้น $. == $next && printเป็นเช่นเดียวกับprint if $. == $next
beasy

อ่าฉันเห็นแล้ว ขอบคุณ! ใน 2 ส่วนแต่ละส่วนเป็นจริงและดำเนินการซ้ำแยกที่อยู่ติดกันของลูป ฉันคิดว่าถ้าประเด็นคือการพิมพ์บรรทัดใด ๆ หลังจากการแข่งขันใด ๆ ที่คุณต้องการที่จะกลับคำสั่งซื้อ (จะทำตัวเหมือนgrep -A1) หากคุณต้องการพิมพ์เฉพาะบรรทัดถัดไป แต่ไม่ตรงกับการจับคู่คุณจะต้องรักษาลำดับนี้เอาไว้ (เพียงสังเกตว่า $ ถัดไปจะถูก
Keith Bentrup

3

ดูเหมือนว่าคุณกำลังใช้เครื่องมือผิดที่นั่น Grep ไม่ได้มีความซับซ้อนฉันคิดว่าคุณต้องการที่จะก้าวขึ้นเป็นเครื่องมือสำหรับงาน:

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

หากคุณพบปัญหาใด ๆ ให้ฉันรู้ฉันคิดว่ามันคุ้มค่าที่จะเรียนรู้บ้างเล็กน้อย awk เป็นเครื่องมือที่ยอดเยี่ยม :)

ps ตัวอย่างนี้ไม่ได้รับรางวัล 'การใช้ประโยชน์จากรางวัลแมว';) http://porkmail.org/era/unix/award.html


3
BTW คุณสามารถข้าม "$ 0" ในการพิมพ์
MichałŠrajer

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.