ลบบรรทัดที่ไม่ได้เริ่มต้นด้วยรูปแบบจากชุดรูปแบบที่กำหนด


11

ฉันมีไฟล์ที่มีข้อมูลเช่นนี้:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc

.. --.

คำถาม: ฉันต้องการลบบรรทัดที่ไม่ได้ขึ้นต้นด้วยสตริงต่อไปนี้:

report  
-th  
-to

นั่นหมายถึงผลลัพธ์ที่ต้องการจะลบจุดและแฮชกลางที่ไม่ต้องการทั้งหมดออกและจะมีลักษณะเช่นนี้:

report aaaaaaaa  
-th bbbbbbbbb  
-to ccccccccc

sed/ awk/ grep/ ฯลฯ วิธีการแก้ปัญหาใด ๆ ที่จะทำงาน

คำตอบ:


15

การใช้sedเพื่อปรับเปลี่ยนไฟล์ในสถานที่:

sed -i '/^\(report\|-t\(h\|o\)\)/!d' your_file

สิ่งนี้แนะนำsedให้ลบบรรทัดทั้งหมดที่ไม่ตรงกับรูปแบบ รูปแบบที่ตัวเองเป็น^(เริ่มต้นของเส้น) ตามด้วยการอย่างใดอย่างหนึ่งreportหรือ-tตามอย่างใดอย่างหนึ่งหรือho

คุณควรทราบว่านี่ไม่ใช่การดัดแปลงแบบแทนที่: sedสร้างสำเนาสำรองชั่วคราวและเขียนทับไฟล์ต้นฉบับด้วย

หากคุณต้องการsedเก็บสำเนาสำรองของไฟล์ดั้งเดิม (ซึ่งอาจเป็นความคิดที่ดีถ้าไฟล์มีข้อมูลที่สำคัญ) ให้-iสลับส่วนขยายเพื่อสร้างไฟล์สำรอง:

sed -i'.bak' -e '/^\(report\|-t\(h\|o\)\)/!d' your_file

จะปรับเปลี่ยนและสร้างการสำรองข้อมูลของเดิมที่เรียกว่าyour_fileyour_file.bak

ข้อความด้านข้าง

โปรดอย่าเข้าใจผิดความตั้งใจของฉันหรือทำผิดที่นี้ แต่ฉันสังเกตเห็นว่าคุณมีคำถามที่เกี่ยวข้องกับการประมวลผล regex / ข้อความที่คล้ายกันมากมาย ผมแนะนำให้คุณเริ่มต้นการเรียนรู้sed, awkและgrepตัวคุณเองที่จะช่วยเพิ่มความเร็วในการผลิตของคุณ อย่าเข้าใจฉันผิดฉันดีใจเกินกว่าจะช่วยได้ (เหมือนคนส่วนใหญ่ที่นี่); เป็นเพียงที่ฉันคิดว่าคุณจะได้รับประโยชน์อย่างมหาศาลจากการเลือกใช้เครื่องมือเหล่านี้สำหรับการใช้ชีวิตประจำวัน

เพียงเพื่อพิสูจน์ว่าผู้คนช่วยเหลือคุณอย่างไรให้พิจารณาข้อเสนอแนะของ @ slm ในความคิดเห็นด้านล่างและอย่าลังเลที่จะแวะมาที่ห้องสนทนานี้เมื่อใดก็ได้สำหรับคำถาม


1
การแสดงออกปกติของคุณดูเหมือนจะคลุมเครือโดยไม่จำเป็น ฉันคิดว่าคุณใช้ตัวอักษรมากกว่าจริง ๆ ถ้าคุณเพิ่งระบุไว้สามตัวเลือกอย่างชัดเจน
nispio

1
@nispio ฉันรู้ แต่ก็น่าจะมีประสิทธิภาพมากกว่านี้หากไฟล์ที่เป็นปัญหามีขนาดใหญ่
โจเซฟอาร์

น่าสนใจ ฉันวัดค่า regexps ในแง่ของความยาวหรือความสามารถในการอ่านเสมอ ฉันไม่เคยคิดมากกับความเร็วในการเรียกใช้งาน ฉันไม่คิดว่าฉันรู้มากพอเกี่ยวกับวิธีการประเมินเพื่อตัดสินว่าอะไรเร็ว แต่ฉันคิดว่ามันเป็นการใช้งานที่เฉพาะเจาะจงด้วยใช่ไหม
nispio

3
ทำซ้ำสิ่งที่โจเซฟพูดเกี่ยวกับการเต็มใจช่วยถ้าคุณมีคำถามทั่วไปที่ไม่เหมาะกับคำถามและคำตอบคุณสามารถลองแชทกับเราได้ที่ห้องสนทนาสำหรับเว็บไซต์นี้ chat.stackexchange.com/rooms/26/unix-and-linux พวกเราหลายคนอาศัยอยู่ที่นั่น 8-)
slm

@slm ขอบคุณสำหรับสิ่งนี้ ฉันจะเพิ่มเข้าไปในคำตอบของฉัน
โจเซฟอาร์

10

คุณสามารถใช้ grep อย่างง่ายสำหรับสิ่งนี้:

$ grep -e '^report\|^-th\|^-to' filename

1
มันไม่มากของเงินฝากออมทรัพย์ แต่คุณสามารถรวม-th/ เข้า-to -t[ho]
เควิน

grep -eหรือegrep
Olivier Dulac

2

การใช้sed:

sed -n -e '/^report\|^-th\|^-to/p' filename

มันไม่มากของเงินฝากออมทรัพย์ แต่คุณสามารถรวม-th/ เข้า-to -t[ho]
เควิน

1
@ เควินนั่นจริง ดูการสนทนาของฉันกับโจเซฟอาร์ในความคิดเห็นต่อคำตอบของเขา
nispio


1

ผู้ถามได้ทำสองคะแนน:

  • ต้องการลบบรรทัดใด ๆ ที่ไม่ขึ้นต้นด้วย "รายงาน" หรือ "-th" หรือ "-to"
  • ผลลัพธ์ที่ต้องการควรลบ "จุดและแฮชที่ไม่ต้องการทั้งหมดเหล่านั้นกลาง"

การแก้ปัญหาในเวลานี้อยู่ที่จุดแรกและยังเป็นที่สอง แต่สมมติว่าไฟล์มีขนาดใหญ่กว่าและมีลักษณะดังนี้:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc
anything else
.. --.
-tp ddd
-tq eee
     -  -----

จะไม่พูดถึงประเด็นที่สองของ OP หรือไม่จำเป็น?

sed -r -i.bak '/^[ |.|-]*$/d' input-file 

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


0

ใช้ Perl:

perl -ne 'print if /^report|^-t[ho]/' filename > newfile

หรือการแก้ไขในสถานที่ (เช่นsed, perlนอกจากนี้ยังจะทำการสำรองข้อมูลชั่วคราวดังนั้นนี้ไม่เป็นความจริงในสถานที่การแก้ไข):

perl -i.bak -ne 'print if /^report|^-t[ho]/' filename

ซึ่งจะทำการคัดลอกไฟล์ต้นฉบับที่เรียกว่าfilename.bakและเขียนทับไฟล์ต้นฉบับของคุณด้วยเวอร์ชันที่แก้ไข

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