พิมพ์บรรทัดเฉพาะในกรณีที่บรรทัดถัดไปไม่มีการแข่งขันที่เฉพาะเจาะจง


12

ฉันพยายามค้นหาไฟล์บันทึกสำหรับกิจกรรมที่บันทึกไม่เสร็จสมบูรณ์ ตัวอย่างเช่นฉันบันทึก "กิจกรรมเริ่มต้นสำหรับ ID 1234 ... " และหากประสบความสำเร็จบรรทัดถัดไปจะเป็น "กิจกรรม 1234 เสร็จสมบูรณ์"

ฉันพยายามรับบรรทัด "เริ่มต้น ... " ที่ไม่ได้ตามด้วยบรรทัด "เสร็จสมบูรณ์" ที่เกี่ยวข้อง

ตัวอย่างไฟล์บันทึก

Starting activity for ID 1234
ID 1234 completed successfully
Starting activity for ID 3423
ID 3423 completed successfully
Starting activity for ID 9876
ID 9876 completed successfully
Starting activity for ID 99889
ID 99889 completed successfully
Starting activity for ID 10011
ID 10011 completed successfully
Starting activity for ID 33367
Starting activity for ID 936819
ID 936819 completed successfully

ในตัวอย่างนี้ฉันจะมองหาผลลัพธ์ที่จะ:

Starting activity for ID 33367

... เนื่องจากยังไม่ได้ตามด้วยบรรทัด "เสร็จสมบูรณ์"

ฉันได้ลองทำด้วยgrepและawkไม่ประสบความสำเร็จมากนัก ฉันคิดว่ามันสามารถทำได้ด้วยหนึ่งในเครื่องมือเหล่านั้น แต่ของฉันgrepและawkสับไม่ได้สูง

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


ฉันไม่คิดว่ามันเป็นเรื่องง่ายด้วย grep + awk แต่คุณช่วยอธิบายหน่อยได้ไหมว่าทำไมคุณถึงทำอย่างนั้น? ผลลัพธ์ของกิจกรรมที่ดำเนินอยู่ทั้งหมดเช่นความสำเร็จหรือไม่สิ้นสุด
เดซี่

@ warl0ck ฉันกำลังมองหา "ยังไม่เสร็จ"
PattMauler

คำตอบ:


10

นี่คือawkทางเลือก:

awk '
  /^Starting/ { I[$5] = $0                  }
  /^ID/       { delete I[$2]                }
  END         { for (key in I) print I[key] }
' infile

เอาท์พุท:

Starting activity for ID 33367

Iอาเรย์ติดตามสิ่งที่รหัสได้รับการเห็น


วิธีนี้ใช้งานได้ดีจริง ๆ เนื่องจากดูเหมือนว่าจะรองรับสถานการณ์ที่บรรทัดบันทึก "เริ่มต้น ... " และ "เสร็จสมบูรณ์ ... " ไม่ได้อยู่ติดกัน / เรียงตามลำดับ ขอบคุณ @Thor!
PattMauler

ยินดีต้อนรับ. สิ่งนี้ควรทำงานได้อย่างมีประสิทธิภาพด้วยอินพุตขนาดเกือบ (โดยพลการ) เนื่องจากมันจะเก็บ ID และเวลาค้นหาเท่านั้นคือ O (1)
ธ.ค.

ดี มีเพียงสิ่งเดียว: ที่ฉันเรียนรู้จาก @RobertL ( unix.stackexchange.com/a/243550/135943 ) คุณไม่จำเป็นต้องกำหนดค่าเพื่อสร้างองค์ประกอบอาร์เรย์ ดังนั้นแทนที่จะคุณก็สามารถใช้I[$5] = 1 I[$5](คุณไม่สนใจเกี่ยวกับคุณค่าคุณเพียงต้องการทำให้องค์ประกอบมีอยู่และเพียงตั้งชื่อให้สำเร็จ)
Wildcard

@ Wildcard: ถูกต้อง แต่หลังจากตรวจสอบคำถามของ OP และ grep like output ที่เป็นหลังแล้วจะเหมาะสมกว่าที่จะจดจำทั้งบรรทัดและเอาต์พุตที่ท้ายที่สุด
Thor

3
sed '$!N;/\n.*completed/d;P;D' <input

นี้จะลบจากการแสดงผลเส้นที่นำเข้าทั้งหมดที่ไม่ได้ตามมาด้วยสายการจับคู่สตริงเสร็จสมบูรณ์


2

นี่คือวิธีที่คุณสามารถทำได้ด้วย GNU sed:

sed -r 'N; /([0-9]+)\n\w+\s+\1/d; P; D' infile
  • N อ่านอีกหนึ่งบรรทัดในพื้นที่รูปแบบ
  • การจับคู่ regex ตรวจสอบว่าพบรหัสที่เหมือนกันหากมีการลบพื้นที่รูปแบบ ( d) และเริ่มต้นรอบใหม่
  • หากไม่ตรงกันให้พิมพ์บรรทัดแรกใน pattern space ( P) และลบ ( D)

ฉันไม่เห็นสิ่งที่ขยายออกไปที่นี่ ... ดังนั้นจึง-rไม่จำเป็นใช่ไหม
Louis Maddox

1
@lmmx: มันเป็นสิ่งจำเป็นเพราะมิฉะนั้นความต้องการของกลุ่มการจับภาพที่จะหนีและเดียวกันจะไปสำหรับ+ปริมาณ
Thor

อาโอเค! ฉันแก้ไขมันและบอกว่าไม่จำเป็นต้องขอบคุณสำหรับความกระจ่าง
Louis Maddox

1

หากการติดตั้งของคุณรองรับ pcregrep ตัวเลือก multiline (-M) จะมีประโยชน์

pcregrep -M -o '\AStarting activity for ID (\d+)\n(?!ID \1)' t.z

กิจกรรมเริ่มต้นสำหรับ ID 33367

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