ส่งคืนเฉพาะส่วนของบรรทัดหลังจากรูปแบบการจับคู่


109

ดังนั้นการดึงเปิดไฟล์ด้วยcatและจากนั้นใช้grepในการรับสายการจับคู่เพียงทำให้ฉันได้รับเมื่อฉันทำงานกับชุดบันทึกเฉพาะที่ฉันจัดการกับ มันต้องการวิธีการจับคู่ลายเส้นกับรูปแบบ แต่เพื่อคืนส่วนของเส้นหลังการจับคู่เท่านั้น ส่วนก่อนและหลังการแข่งขันจะแตกต่างกันอย่างสม่ำเสมอ ฉันได้เล่นโดยใช้sedหรือawkแต่ไม่สามารถหาวิธีกรองบรรทัดเพื่อลบส่วนหนึ่งก่อนการแข่งขันหรือเพียงแค่คืนส่วนหลังการแข่งขันทั้งคู่จะทำงาน นี่คือตัวอย่างของบรรทัดที่ฉันต้องการกรอง:

2011-11-07T05:37:43-08:00 <0.4> isi-udb5-ash4-1(id1) /boot/kernel.amd64/kernel: [gmp_info.c:1758](pid 40370="kt: gmp-drive-updat")(tid=100872) new group: <15,1773>: { 1:0-25,27-34,37-38, 2:0-33,35-36, 3:0-35, 4:0-9,11-14,16-32,34-38, 5:0-35, 6:0-15,17-36, 7:0-16,18-36, 8:0-14,16-32,34-36, 9:0-10,12-36, 10-11:0-35, 12:0-5,7-30,32-35, 13-19:0-35, 20:0,2-35, down: 8:15, soft_failed: 1:27, 8:15, stalled: 12:6,31, 20:1 }

ส่วนที่ฉันต้องการคือทุกอย่างหลังจาก "จนตรอก"

เบื้องหลังที่อยู่เบื้องหลังคือฉันสามารถค้นหาได้ว่ามีบางสิ่งที่แผงลอย:

cat messages | grep stalled | wc -l

สิ่งที่ฉันต้องทำคือค้นหาว่ามีโหนดบางจุดค้างอยู่กี่ครั้ง (ระบุโดยส่วนก่อนแต่ละโคลอนหลังจาก "จนตรอก" ถ้าฉันแค่ grep สำหรับสิ่งนั้น (เช่น 20 :) มันอาจส่งคืนบรรทัดที่อ่อนนุ่มล้มเหลว แต่ ไม่มีแผงลอยซึ่งไม่ได้ช่วยฉันฉันต้องกรองเฉพาะส่วนที่ค้างไว้ดังนั้นฉันจึงสามารถ grep สำหรับโหนดที่เฉพาะเจาะจงจากผู้ที่ได้จนตรอก

สำหรับเจตนาและวัตถุประสงค์ทั้งหมดนี้เป็นระบบ freebsd ที่มี core GNU มาตรฐาน utils แต่ฉันไม่สามารถติดตั้งอะไรเพิ่มเติมเพื่อช่วย


@Gilles, แปลกที่ไม่ปรากฏขึ้นเมื่อฉันค้นหาแม้ว่าฉันไม่ได้ใช้ชื่อที่ฉันไปด้วยในที่สุด ... แต่มันไม่ปรากฏในหน้าจอด้านล่างชื่อของฉัน อย่างไรก็ตามนั่นอาจทำให้ฉันได้ในที่ที่ฉันต้องการถึงแม้ว่าฉันต้องการทั้งบรรทัดหลังการแข่งขันไม่ใช่คำแรก - แต่อาจไม่ได้เปลี่ยนแปลงอะไรมากมาย
MaQleod

ชื่อของมันถูกดูด ฉันขโมยของคุณซึ่งเป็นสิ่งที่ดีมาก ใช้sedวิธีแก้ปัญหาและไม่รักษาช่องว่างพิเศษ
Gilles

@Gilles นั่นเป็นสิ่งที่ฉันไม่แน่ใจว่าจะทำอย่างไร ฉันยังคงเรียนรู้ที่จะนั่ง
MaQleod

คล้ายกับunix.stackexchange.com/questions/24089/…เช่นกัน
ทิมเคนเนดี้

1
@ shaa0601 ฉันไม่เข้าใจคำถามของคุณมันเป็นเรื่องยากโดยเฉพาะอย่างยิ่งในการติดตามความคิดเห็นโดยไม่มีการจัดรูปแบบ ถามคำถามใหม่ที่มีในตัว
Gilles

คำตอบ:


141

sedเครื่องมือที่ยอมรับสำหรับการที่จะเป็น

sed -n -e 's/^.*stalled: //p'

คำอธิบายโดยละเอียด:

  • -n หมายถึงไม่พิมพ์สิ่งใดโดยปริยาย
  • -e ตามด้วยคำสั่ง sed
  • s เป็นคำสั่งการแทนที่รูปแบบ
  • นิพจน์ทั่วไป^.*stalled:ตรงกับรูปแบบที่คุณต้องการรวมถึงข้อความก่อนหน้าใด ๆ ( .*หมายถึงข้อความใด ๆ โดยมีตัวย่อ^เพื่อบอกว่าการจับคู่เริ่มต้นที่จุดเริ่มต้นของบรรทัด) โปรดทราบว่าหากstalled:เกิดขึ้นหลายครั้งในบรรทัดสิ่งนี้จะตรงกับเหตุการณ์ล่าสุด
  • การแข่งขันคือทุกสิ่งที่อยู่ในแถวจนถึงstalled:จะถูกแทนที่ด้วยสตริงว่าง (เช่นถูกลบ)
  • pหมายถึงขั้นสุดท้ายในการพิมพ์สายแปลง

หากคุณต้องการรักษาส่วนที่ตรงกันไว้ให้ใช้การอ้างอิงย้อนกลับ: \1ในส่วนการทดแทนกำหนดสิ่งที่อยู่ภายในกลุ่ม\(…\)ในรูปแบบ ที่นี่คุณสามารถเขียนstalled:อีกครั้งในส่วนทดแทน คุณลักษณะนี้มีประโยชน์เมื่อรูปแบบที่คุณต้องการนั้นกว้างกว่าสตริงธรรมดา

sed -n -e 's/^.*\(stalled: \)/\1/p'

บางครั้งคุณอาจต้องการลบส่วนของบรรทัดหลังการแข่งขัน คุณสามารถรวมไว้ในการแข่งขันโดยรวม.*$ที่ส่วนท้ายของรูปแบบ (ข้อความใด ๆ.*ตามด้วยท้ายบรรทัด$) ยกเว้นว่าคุณใส่ส่วนนั้นไว้ในกลุ่มที่คุณอ้างอิงในข้อความการแทนที่จุดสิ้นสุดของบรรทัดจะไม่อยู่ในผลลัพธ์

เป็นภาพประกอบเพิ่มเติมของกลุ่มและการอ้างอิงย้อนกลับคำสั่งนี้จะสลับส่วนก่อนการแข่งขันและส่วนหลังการแข่งขัน

sed -n -e 's/^\(.*\)\(stalled: \)\(.*\)$/\3\2\1/p'

ฉันลองสองตัวอย่างแรกและดูเหมือนว่าจะแฮงค์ ฉันไม่ได้รับข้อความแสดงข้อผิดพลาดและไม่ได้รับพรอมต์ใหม่ไม่มีอะไรเลย
MaQleod

2
@MaQleod โอ้กำลังรออินพุตจากอินพุตมาตรฐานซึ่งนี่คือเทอร์มินัลเพราะคุณยังไม่ได้เปลี่ยนทิศทาง ที่นี่คุณจะทำการเปลี่ยนเส้นทางอินพุตsed … <messagesเนื่องจากคุณต้องการประมวลผลข้อมูลจากไฟล์ somecommand | sed …ที่จะทำหน้าที่เกี่ยวกับข้อมูลการผลิตโดยคำสั่งอื่นคุณต้องการใช้ท่อ:
Gilles

1
ขวาสิ้นวันดับที่นั่น คำสั่งทำงานได้อย่างสมบูรณ์ขอบคุณ
MaQleod

1
คำอธิบายที่ดีที่สุดที่ฉันเคยเห็นมา - ขอบคุณ!
Jon Wadsworth

1
รุ่น @ungalcrys สั้นกว่าของอะไร สิ่งนี้ไม่เทียบเท่ากับคำสั่งใด ๆ ในคำตอบของฉัน ฉันขอแนะนำให้เขียนsed 's/^.*stalled//'เพราะ-rเป็นเฉพาะสำหรับ Linux และไม่สามารถทำงานบนระบบอื่น ๆ เช่น macOS และที่นี่คุณไม่ได้รับประโยชน์ใด ๆ จากมัน
Gilles

72

เครื่องมือบัญญัติอื่น ๆ ที่คุณใช้อยู่แล้วgrep::

ตัวอย่างเช่น:

grep -o 'stalled.*'

มีผลลัพธ์เช่นเดียวกับตัวเลือกที่สองของ Gilles:

sed -n -e 's/^.*\(stalled: \)/\1/p'

-oธงส่งกลับ--only-matchingเป็นส่วนหนึ่งของการแสดงออกจึงไม่สายทั้งหมดซึ่งเป็น - แน่นอน - ทำตามปกติโดย grep

ในการลบ "จนตรอก:" ออกจากผลลัพธ์เราสามารถใช้เครื่องมือมาตรฐานรุ่นที่สามแล้วตัด:

grep -o 'stalled.*' | cut -f2- -d:

cutคำสั่งใช้คั่น:และพิมพ์ข้อมูล 2 จนจบ มันเป็นเรื่องของความพึงพอใจแน่นอน แต่cutไวยากรณ์ที่ฉันพบนั้นง่ายต่อการจดจำ


1
ขอบคุณสำหรับการกล่าวถึง-oตัวเลือก! ฉันต้องการชี้ให้เห็นว่าgrepไม่รู้จัก\nบรรทัดใหม่ดังนั้นตัวอย่างแรกของคุณจะจับคู่กับnอักขระตัวแรกเท่านั้น ยกตัวอย่างเช่นส่งกลับสตริงecho "Hello Anne" | grep -o 'A[^\n]*' Aอย่างไรก็ตามecho "Hello Anne" | grep -o 'A.*'ส่งคืนค่าที่คาดไว้Anneเนื่องจาก.ตรงกับอักขระใด ๆ ยกเว้นขึ้นบรรทัดใหม่
adamlamar

1
โปรดทราบว่าเครื่องหมายคำพูดรอบcutตัวคั่น-d':'จะถูกลบโดย @poige ฉันคิดว่ามันง่ายต่อการจดจำด้วยคำพูดเช่นด้วยหรือ-d' ' -d';'
Anne van Rossum

ตามการค้นพบของคุณคุณควรจำไว้ว่าให้ใช้เครื่องหมายคำพูดด้วย-f 2เช่นกัน อย่างจริงจังทำไมไม่
poige

เนื่องจากตัวคั่นเช่นเซมิโคลอน;มากกว่าโคลอน:จะถูกตีความแตกต่างกันถ้าไม่ยกมา แน่นอนว่ามันเป็นพฤติกรรมที่สมเหตุสมผล แต่ฉันก็ยังต้องการพึ่งพาความทรงจำของกล้ามเนื้อ ฉันไม่ชอบพูดตัวคั่นหนึ่งครั้ง แต่ไม่ใช่ในเวลาอื่น แค่ความชอบส่วนตัวอย่างที่ฉันพูดไปก่อนหน้านี้: จดจำได้ง่ายกว่า
Anne van Rossum

ระยะเวลาที่เป็นส่วนหนึ่งของ.*เป็นสิ่งจำเป็นที่ทำงานได้ดีสำหรับฉัน: cat filename | grep 'Return only this line xyz text' | grep -o 'xyz.*' ผลตอบแทนxyz text
รอน

4

ฉันเคยifconfig | grep eth0 | cut -f3- -d:ใช้มัน

    [root@MyPC ~]# ifconfig
    eth0  Link encap:Ethernet  HWaddr AC:B4:CA:DD:E6:F8
          inet addr:192.168.0.2  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:78998810244 errors:1 dropped:0 overruns:0 frame:1
          TX packets:20113430261 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:110947036025418 (100.9 TiB)  TX bytes:15010653222322 (13.6 TiB)

และทำให้มันเป็นแบบนี้

    [root@MyPC ~]# ifconfig | grep eth0 | cut -f3- -d:
    C4:7A:4D:F6:B8

2
นี่ตอบคำถามหรือไม่
Stephen Rauch

1
คุณสามารถใช้cat /sys/class/net/*/addressโดยไม่ต้องแยกวิเคราะห์
Anne van Rossum

1

อีกหนึ่งเครื่องมือบัญญัติที่คุณพิจารณาแล้วawkสามารถใช้กับบรรทัดต่อไปนี้:

awk -F"stalled" '/stalled/{print $2}' messages

คำอธิบายโดยละเอียด:

  • -Fกำหนดตัวคั่นสำหรับบรรทัดคือ "จนตรอก" ทุกอย่างก่อนที่ตัวคั่นจะได้รับการจัดการด้วย$1และทุกอย่างหลังจาก$2นั้น
  • /reg-ex/ ค้นหานิพจน์ทั่วไปที่ตรงกันในกรณีนี้ "จนตรอก"
  • {print $<n>}- พิมพ์คอลัมน์ n เนื่องจากตัวคั่นของคุณถูกกำหนดเป็นจนตรอกทุกอย่างหลังจากที่ถูกหยุดจะถือว่าเป็นคอลัมน์ที่สอง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.