ดอนอาจจะดีกว่าในกรณีส่วนใหญ่ แต่เพียงในกรณีที่ไฟล์นั้นจริงๆขนาดใหญ่และคุณไม่ได้รับsedการจัดการไฟล์สคริปต์ที่มีขนาดใหญ่(ซึ่งสามารถเกิดขึ้นได้ที่ประมาณ 5000 + สายของสคริปต์) , ที่นี่มันเป็นธรรมดาsed:
sed -ne:t -e"/\n.*$match/D" \
-e'$!N;//D;/'"$match/{" \
-e"s/\n/&/$A;t" \
-e'$q;bt' -e\} \
-e's/\n/&/'"$B;tP" \
-e'$!bt' -e:P -e'P;D'
นี่คือตัวอย่างของสิ่งที่เรียกว่าหน้าต่างบานเลื่อนบนอินพุต มันทำงานได้โดยการสร้างบัฟเฟอร์การค้นหาล่วงหน้าของ$B-count บรรทัดก่อนที่จะพยายามพิมพ์อะไร
และที่จริงแล้วฉันควรจะชี้แจงประเด็นก่อนหน้านี้: ตัว จำกัด ประสิทธิภาพหลักสำหรับทั้งโซลูชันนี้และของ don จะเกี่ยวข้องโดยตรงกับช่วงเวลา การแก้ปัญหานี้จะชะลอตัวกับช่วงเวลาที่มีขนาดใหญ่ขนาดในขณะที่ดอนจะชะลอตัวที่มีขนาดใหญ่ช่วงความถี่ กล่าวอีกนัยหนึ่งถึงแม้ว่าไฟล์อินพุตมีขนาดใหญ่มากหากช่วงเวลาที่เกิดขึ้นจริงยังคงไม่บ่อยนักโซลูชันของเขาอาจเป็นวิธีที่จะไป อย่างไรก็ตามหากขนาดช่วงเวลานั้นค่อนข้างจัดการได้และมีแนวโน้มที่จะเกิดขึ้นบ่อยนี่เป็นวิธีแก้ปัญหาที่คุณควรเลือก
ดังนั้นนี่คือขั้นตอนการทำงาน:
- หาก
$matchพบในพื้นที่รูปแบบนำหน้าด้วย\newline sedจะลบซ้ำDทุก\newline ที่นำหน้า
- ฉันล้าง
$matchพื้นที่รูปแบบออกหมดก่อน - แต่เพื่อจัดการกับการทับซ้อนกันได้ง่ายการทิ้งแลนด์มาร์กไว้ดูเหมือนจะดีกว่ามาก
- ฉันยังพยายามที่
s/.*\n.*\($match\)/\1/จะลองมันในครั้งเดียวและหลบห่วง แต่เมื่อ$A/$Bมีขนาดใหญ่Dวง elete พิสูจน์ได้เร็วขึ้นมาก
- แล้วเราดึงใน
Nสายต่อของการป้อนข้อมูลนำหน้าด้วย\nตัวคั่น ewline และลองอีกครั้งDหนึ่งคำ/\n.*$match/อีกครั้งโดยอ้างถึงใช้มากที่สุดเมื่อเร็ว ๆ นี้การแสดงออกของเราอย่างสม่ำเสมอ w ///
- หากการเว้นวรรครูปแบบตรงกัน
$matchก็สามารถทำได้$matchที่ส่วนหัวของบรรทัด - ทุก$Bบรรทัด efore ได้รับการล้าง
- ดังนั้นเราจึงเริ่มวนรอบ
$After
- การทำงานของวงนี้แต่ละคนเราจะพยายาม
s///ubstitute สำหรับ&ตัวเอง$ATH \nตัวอักษร ewline ในพื้นที่รูปแบบและหากประสบความสำเร็จtคือจะสาขาเรา - และเราทั้ง$Aกันชนแจก - ออกของสคริปต์ทั้งหมดจะเริ่มต้นสคริปต์ที่มาจากด้านบน ด้วยอินพุตบรรทัดถัดไปหากมี
- หาก
tEST ไม่ประสบความสำเร็จเราจะbกลับไปที่:tฉลาก op และเรียกเก็บเงินจากอินพุตอื่น - อาจเริ่มวนซ้ำหาก$matchเกิดขึ้นขณะรวบรวม$After
- หากเราได้รับที่ผ่านมา
$matchวงฟังก์ชั่นแล้วเราจะพยายามที่จะprint $บรรทัดสุดท้ายว่านี้มันเป็นและถ้า!ไม่พยายามที่จะs///ubstitute สำหรับ&ตัวเอง$BTH \nตัวอักษร ewline ในพื้นที่รูปแบบ
- เราจะทำ
tสิ่งนี้เช่นกันและหากประสบความสำเร็จเราจะแยกสาขาไปที่:Pป้ายกำกับ
- ถ้าไม่ใช่เราจะแยกสาขากลับไปที่
:top และรับสายอินพุตอื่นต่อท้ายบัฟเฟอร์
- ถ้าเราทำให้มันไป
:Print เราจะPrint แล้วDหนึ่งคำขึ้นไปครั้งแรก\newline ในพื้นที่รูปแบบและรันสคริปต์จากด้านบนกับสิ่งที่ยังคง
ดังนั้นเวลานี้ถ้าเราทำ A=2 B=2 match=5; seq 5 | sed...
พื้นที่รูปแบบสำหรับการทำซ้ำครั้งแรกที่:Print จะมีลักษณะดังนี้:
^1\n2\n3$
และนั่นคือวิธีsedรวบรวม$Bบัฟเฟอร์ efore และsedพิมพ์ไปยัง$Bบรรทัดเอาต์พุต - นับบรรทัดด้านหลังอินพุตที่รวบรวมไว้ ซึ่งหมายความว่าตามตัวอย่างก่อนหน้าของเราsedจะPrint 1to output แล้วลบออกDและส่งกลับไปด้านบนสุดของสคริปต์เพื่อกำหนดพื้นที่รูปแบบซึ่งมีลักษณะดังนี้:
^2\n3$
... และที่ด้านบนสุดของสคริปต์Nบรรทัดอินพุตอินพุทจะถูกดึงออกมาและการทำซ้ำครั้งถัดไปจะมีลักษณะดังนี้:
^2\n3\n4$
ดังนั้นเมื่อเราพบสิ่งแรกที่เกิดขึ้น5ในอินพุทพื้นที่รูปแบบจะมีลักษณะดังนี้:
^3\n4\n5$
จากนั้นDวง elete ก็จะเตะเข้าและเมื่อผ่านไปมันจะดูเหมือน:
^5$
และเมื่อNดึงสายสัญญาณเข้า ext จะsedกระทบ EOF และออก เมื่อถึงเวลานั้นมันจะมีเพียงPสาย rinted 1 และ 2 เท่านั้น
นี่คือตัวอย่างการเรียกใช้:
A=8 B=7 match='[24689]0'
seq 100 |
sed -ne:t -e"/\n.*$match/D" \
-e'$!N;//D;/'"$match/{" \
-e"s/\n/&/$A;t" \
-e'$q;bt' -e\} \
-e's/\n/&/'"$B;tP" \
-e'$!bt' -e:P -e'P;D'
ภาพพิมพ์นั้น:
1
2
3
4
5
6
7
8
9
10
11
12
29
30
31
32
49
50
51
52
69
70
71
72
99
100