วิธีลบบรรทัดว่างที่เริ่มต้นจากบรรทัดที่ 5


10

ฉันมีสิ่งนี้:

sed -i '/^$/d' temp_spec.rb

ซึ่งลอกบรรทัดว่างและทำงานได้ดี ฉันจะทำให้มันใช้งานได้เฉพาะกับบรรทัดที่ 5-999 (หรือ 5 ถึงจุดสิ้นสุดของไฟล์)

ฉันเหนื่อย:

sed -n5,999 -i '/^$/d' temp_spec.rb
sed '5,999!d/^$/d' temp_spec.rb

แต่ไม่ทำงาน (ไม่มีข้อผิดพลาด)


เพื่อให้แน่ใจว่า: คุณต้องการให้บรรทัดที่ 1 ถึง 4 ไม่ว่าจะว่างเปล่าหรือไม่หรือคุณต้องการลบบรรทัดที่ 1 ถึง 4 ไม่ว่าจะว่างหรือไม่ (จนถึงตอนนี้ผมสันนิษฐานว่าในอดีต แต่คำสั่งที่สองที่คุณพยายามทำให้ฉันสงสัย.)
Uwe

คำตอบ:


12

หากคุณต้องการลบบรรทัดว่างทั้งหมดที่เริ่มต้นด้วยบรรทัด 5 และเก็บบรรทัด 1 ถึง 4 คุณสามารถใช้

sed -i '5,${;/^$/d;}' temp_spec.rb

the {เป็นตัวดำเนินการจัดกลุ่มดังนั้นคำสั่งแรกจึง5,${หมายถึง "จากบรรทัดที่ 5 จนถึงจุดสิ้นสุดของอินพุต ( $) ดำเนินการคำสั่งต่อไปนี้จนกว่าจะมีการจับคู่}" คำสั่งระหว่าง{และ}สามารถนำหน้าได้อีกครั้งโดยที่อยู่ดังนั้นคำสั่งภายใน/^$/dหมายถึง "ถ้าไม่มีอะไรระหว่างการเริ่มต้น ( ^) และสิ้นสุด ( $) ของบรรทัดลบมัน" คำสั่ง sed สามารถคั่นด้วย;ได้ (นี่เป็นคุณสมบัติที่ไม่ดีของ sed แต่ก็รองรับการใช้งาน sed ส่วนใหญ่ แต่ก็ไม่ได้พกพาได้ทั้งหมด ) ตามที่ Hauke ​​ระบุไว้ตัวเลือก;after {เป็นตัวเลือก ก่อนหน้า}นั้นจำเป็นต้องมีแม้ว่า

หากคุณต้องการลบบรรทัดว่างทั้งหมดที่เริ่มต้นด้วยบรรทัดที่ 5 และลบบรรทัดที่ 1 ถึง 4 ได้ง่ายขึ้น:

sed -i '1,4d;/^$/d' temp_spec.rb

ดี ฉันไม่รู้ว่าที่อยู่สามารถซ้อนกันได้ สำหรับฉันมันใช้งานได้โดยไม่ต้องมีผู้นำ;ด้วย
Hauke ​​Laging

;อ๋อคุณขวาเกี่ยวกับครั้งแรก
Uwe

@Hauke ​​Laging คุณสามารถแยกคำสั่งในสคริปต์ sed โดย ';' แทนที่จะวางลงบนเส้นแยก นั่นคือคุณสมบัติ "ไม่มีเอกสาร"
Predrag Punosevac


2
sed '5,${s/^$//; t delete; b end; : delete; d; : end;}' temp_spec.rb

แก้ไข 1:

ฉันควรจะอธิบายเรื่องนี้ดังนั้น ...

สิ่งนี้มีความซับซ้อนโดยไม่จำเป็น {}ผมไม่ทราบว่าช่วงที่อยู่ภายในได้รับอนุญาต ดังนั้นฉันจึงต้องแสดง "ลบบรรทัดว่าง" ต่างออกไป คำสั่งแกนtซึ่งเป็น sed if ... thenของวิธีการ Tจะง่ายกว่านี้ แต่ใช้ได้สำหรับ GNU เท่านั้น ฉันอ้างถึงหน้าคน:

t label: หากในฐานะ /// ทำการทดแทนได้สำเร็จตั้งแต่อ่านบรรทัดสุดท้ายแล้วและตั้งแต่คำสั่ง t หรือ T ครั้งสุดท้ายให้แตกสาขาเป็นเลเบล หากไม่ระบุเลเบลให้แยกสาขาจนสุดสคริปต์

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

หากsทำ "การแทนที่" แสดงว่าบรรทัดนั้นว่างเปล่า ในกรณีนั้นคำสั่งdจะถูกดำเนินการ ไม่อย่างนั้นจะต้องทำอะไร เช่นเดียวกับที่tไม่กระโดดในกรณีของการsกระทำฉันต้องการคำสั่ง branch bเพื่อข้ามไปยังจุดสิ้นสุดของสคริปต์ : labelเป็นเป้าหมายสาขา เหมือนgotoย้อนกลับไปในยุคมืด (เมื่อถูกประดิษฐ์ ... te-hee)

อีกตัวเลือกหนึ่งคือให้s"แทนที่" บรรทัดที่ไม่ว่างทั้งหมดทำให้sซับซ้อนมากขึ้น แต่ส่วนที่เหลือของคำสั่งง่ายขึ้น:

sed '5,${s/^\(..*\)$/\1/; t end; d; : end;}' input

^..*$หมายถึง "บรรทัดที่ไม่ว่างเปล่า" และ\1หมายถึง "เนื้อหาของวงเล็บแรก"


คำอธิบายเล็กน้อยเพื่อประโยชน์ของ OP (ฉันสามารถรู้สึกสมองของพวกเขาพยายามที่จะคลานผ่านหูอ่านนี้ ... )
vonbrand
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.