คำสั่งทำให้ '1! G; h; $! d' กลับเนื้อหาของไฟล์ได้อย่างไร


20

คำถามของฉันมีความเกี่ยวข้องกับsedการแก้ปัญหา -specific ได้รับในคำตอบนี้สำหรับคำถามนี้grepping ย้อนกลับ sed/ grepแก้ปัญหาที่ฉันไม่สามารถที่จะถอดรหัสเป็นหนึ่งต่อไปนี้:

sed '1!G;h;$!d' file

มีคนช่วยถอดรหัสคำสั่งนี้ได้ไหม

ฉันรู้จากความรู้ VI (M) ว่า G หมายถึงบรรทัดสุดท้ายของไฟล์และในบางกรณี (!) ตามด้วยที่อยู่ทำงานเล็กน้อยเช่นgrep -vที่จะบอกว่ามันจะไม่ตรงกับบรรทัดนั้น แต่โดยรวมสคริปต์แบบอินไลน์ข้างต้นอยู่เหนือฉัน


3
... ช้ามาก ...
mikeserv

1
ในฐานะที่เป็นคำแนะนำ mikeserv หนึ่งควรทราบว่าsedสูตรที่ยุ่งยากนี้เป็นวิธีที่ซับซ้อนมาก (O (n ^ 2/2)) ในการย้อนกลับบรรทัดในไฟล์ มันจะช้าสำหรับไฟล์ที่มีจำนวนบรรทัดมาก สำหรับทางเลือกอื่น ๆ ในการกลับรายการคำสั่งซื้อตามบรรทัดที่มีประสิทธิภาพมากขึ้นtacจาก GNU coreutils
arielf

คำตอบ:


35

สิ่งนี้จะกลับรายการไฟล์ทีละบรรทัด

sed '1! G; h; $! d' ไฟล์

ครั้งแรกที่sedมีพื้นที่ถือและพื้นที่รูปแบบ เราต้องแยกแยะความแตกต่างระหว่างพวกเขาก่อนที่จะมุ่งเน้นไปที่คำสั่งเฉพาะนั้น

เมื่อsedอ่านบรรทัดใหม่มันจะถูกโหลดในพื้นที่รูปแบบ ดังนั้นพื้นที่นั้นจะถูกเขียนทับทุกครั้งที่มีการประมวลผลบรรทัดใหม่ ในทางตรงกันข้ามพื้นที่พักมีความสอดคล้องมากกว่าการประมวลผลทั้งหมดและค่าที่สามารถเก็บไว้ที่นั่นสำหรับการใช้งานในภายหลัง


ไปที่คำสั่ง:

มี 3 คำสั่งในการแถลงครั้งนี้มี1!G, hและ$!d

  • 1!Gหมายถึงว่าGคำสั่งจะถูกดำเนินการในบรรทัดยกเว้นคนแรกที่ทุกคน (คน!ขัดแย้ง1) Gหมายถึงการผนวกสิ่งที่อยู่ในพื้นที่พักไว้ในพื้นที่รูปแบบ

  • hใช้กับทุกบรรทัด มันจะคัดลอกพื้นที่รูปแบบไปยังพื้นที่พัก (และเขียนทับมัน)

  • $!dใช้กับทุกบรรทัดยกเว้นบรรทัดสุดท้าย ( $แทนบรรทัดสุดท้าย, !คัดค้าน) dเป็นคำสั่งเพื่อลบบรรทัด (พื้นที่รูปแบบ)


  1. ตอนนี้เมื่ออ่านบรรทัดแรกแล้วให้sedเรียกใช้งานhคำสั่ง บรรทัดแรกจะถูกคัดลอกไปยังพื้นที่พัก จากนั้นจะถูกลบเนื่องจากตรงกับ$!เงื่อนไข sedดำเนินการต่อด้วยบรรทัดที่สอง
  2. บรรทัดที่สองตรงกับเงื่อนไข1!(ไม่ใช่บรรทัดแรก) ดังนั้นพื้นที่พัก (ซึ่งมีบรรทัดแรก) จะถูกผนวกเข้ากับพื้นที่รูปแบบ (ซึ่งมีบรรทัดที่สอง) หลังจากนั้นในพื้นที่รูปแบบขณะนี้มีบรรทัดที่สองตามด้วยบรรทัดแรกคั่นด้วยบรรทัดใหม่ ตอนนี้hคำสั่งใช้ (เหมือนในทุกบรรทัด); ทั้งหมดที่อยู่ในพื้นที่รูปแบบจะถูกคัดลอกไปยังพื้นที่พัก คำสั่งที่สาม ( $!d) ใช้: บรรทัดจะถูกลบออกจากพื้นที่รูปแบบ
  3. ขั้นตอนที่ 2 เสร็จแล้วกับทุกบรรทัด เราข้ามไปที่บรรทัดสุดท้าย
  4. ในบรรทัดสุดท้าย ( $) เกือบทั้งหมดของขั้นตอนที่ 2 เสร็จสิ้น แต่ไม่ใช่ส่วนลบ ( d) sedเมื่อเรียกใช้โดยไม่-nพิมพ์พื้นที่รูปแบบโดยอัตโนมัติเมื่อสิ้นสุดการประมวลผลสำหรับแต่ละบรรทัดอินพุต ดังนั้นเมื่อไม่ถูกลบพื้นที่รูปแบบจะถูกพิมพ์ ตอนนี้มันมีทุกบรรทัดในการสั่งซื้อที่ตรงกันข้าม

1
@Geek No hคำสั่งคัดลอกพื้นที่รูปแบบไปยังพื้นที่พักซึ่งยังคงอยู่จนกว่าจะsedสิ้นสุด หลังจากสิ้นสุดสคริปต์ทุกอย่างจะถูกล้างเพราะไบนารีออกจาก
ความโกลาหล

2
เราสามารถคิดถึงพื้นที่ที่ถูกพักอย่างรีจิสเตอร์เป็นกลุ่มได้หรือไม่? พวกเขายังมีหมายเลขหรือไม่ หรือมีเพียงหนึ่งในพวกเขา?
Geek

2
@Geek sedมีพื้นที่สำหรับเก็บข้อมูลเดียวเท่านั้น มันเหมือนกับตัวแปรที่มีบางอย่าง
ความโกลาหล

1
@ user1717828 หากเราไม่พิมพ์บรรทัดแรกเมื่อประมวลผล เนื่องจาก sed ไม่ได้ถูกเรียกใช้ด้วย-nเราต้องลบทุกบรรทัดยกเว้นบรรทัดสุดท้าย ที่บรรทัดสุดท้าย sed ผนวกทุกอย่างจากพื้นที่พักไว้ไปยังพื้นที่รูปแบบ และเนื่องจากdคำสั่งจะไม่ถูกดำเนินการบรรทัดจะถูกพิมพ์ (บรรทัดนี้มีตอนนี้ไฟล์ทั้งหมดกลับรายการ)
ความโกลาหล

1
(1) คำถามย่อย / การสังเกตของ OP (ในความคิดเห็น) คือ“ ดังนั้นhคำสั่งในบรรทัดสุดท้ายจะเรียงลำดับของ no-op” (พร้อมการเน้นเพิ่มเติมและการถอดความเล็กน้อย) เขาพูดถูก; เมื่อsedมีการประมวลผลที่ผ่านมาสายของการป้อนข้อมูลที่Gอ่านพื้นที่การระงับ (เพื่อผนวกกับพื้นที่รูปแบบ) และจากนั้นhคัดลอกพื้นที่รูปแบบไปยังพื้นที่การระงับซึ่งไม่เคยอ้างอิงอีกครั้ง เราสามารถก็เช่นกันพูดหรือsed 'G;$!h;$!d' sed 'G;$!{h;d}'(2) เราสามารถหลีกเลี่ยงการใช้โดยกล่าวว่าd sed -n 'G;h;$p'
สกอตต์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.