ดอนอาจจะดีกว่าในกรณีส่วนใหญ่ แต่เพียงในกรณีที่ไฟล์นั้นจริงๆขนาดใหญ่และคุณไม่ได้รับ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
พบในพื้นที่รูปแบบนำหน้าด้วย\n
ewline sed
จะลบซ้ำD
ทุก\n
ewline ที่นำหน้า
- ฉันล้าง
$match
พื้นที่รูปแบบออกหมดก่อน - แต่เพื่อจัดการกับการทับซ้อนกันได้ง่ายการทิ้งแลนด์มาร์กไว้ดูเหมือนจะดีกว่ามาก
- ฉันยังพยายามที่
s/.*\n.*\($match\)/\1/
จะลองมันในครั้งเดียวและหลบห่วง แต่เมื่อ$A/$B
มีขนาดใหญ่D
วง elete พิสูจน์ได้เร็วขึ้นมาก
- แล้วเราดึงใน
N
สายต่อของการป้อนข้อมูลนำหน้าด้วย\n
ตัวคั่น ewline และลองอีกครั้งD
หนึ่งคำ/\n.*$match/
อีกครั้งโดยอ้างถึงใช้มากที่สุดเมื่อเร็ว ๆ นี้การแสดงออกของเราอย่างสม่ำเสมอ w //
/
- หากการเว้นวรรครูปแบบตรงกัน
$match
ก็สามารถทำได้$match
ที่ส่วนหัวของบรรทัด - ทุก$B
บรรทัด efore ได้รับการล้าง
- ดังนั้นเราจึงเริ่มวนรอบ
$A
fter
- การทำงานของวงนี้แต่ละคนเราจะพยายาม
s///
ubstitute สำหรับ&
ตัวเอง$A
TH \n
ตัวอักษร ewline ในพื้นที่รูปแบบและหากประสบความสำเร็จt
คือจะสาขาเรา - และเราทั้ง$A
กันชนแจก - ออกของสคริปต์ทั้งหมดจะเริ่มต้นสคริปต์ที่มาจากด้านบน ด้วยอินพุตบรรทัดถัดไปหากมี
- หาก
t
EST ไม่ประสบความสำเร็จเราจะb
กลับไปที่:t
ฉลาก op และเรียกเก็บเงินจากอินพุตอื่น - อาจเริ่มวนซ้ำหาก$match
เกิดขึ้นขณะรวบรวม$A
fter
- หากเราได้รับที่ผ่านมา
$match
วงฟังก์ชั่นแล้วเราจะพยายามที่จะp
rint $
บรรทัดสุดท้ายว่านี้มันเป็นและถ้า!
ไม่พยายามที่จะs///
ubstitute สำหรับ&
ตัวเอง$B
TH \n
ตัวอักษร ewline ในพื้นที่รูปแบบ
- เราจะทำ
t
สิ่งนี้เช่นกันและหากประสบความสำเร็จเราจะแยกสาขาไปที่:P
ป้ายกำกับ
- ถ้าไม่ใช่เราจะแยกสาขากลับไปที่
:t
op และรับสายอินพุตอื่นต่อท้ายบัฟเฟอร์
- ถ้าเราทำให้มันไป
:P
rint เราจะP
rint แล้วD
หนึ่งคำขึ้นไปครั้งแรก\n
ewline ในพื้นที่รูปแบบและรันสคริปต์จากด้านบนกับสิ่งที่ยังคง
ดังนั้นเวลานี้ถ้าเราทำ A=2 B=2 match=5; seq 5 | sed...
พื้นที่รูปแบบสำหรับการทำซ้ำครั้งแรกที่:P
rint จะมีลักษณะดังนี้:
^1\n2\n3$
และนั่นคือวิธีsed
รวบรวม$B
บัฟเฟอร์ efore และsed
พิมพ์ไปยัง$B
บรรทัดเอาต์พุต - นับบรรทัดด้านหลังอินพุตที่รวบรวมไว้ ซึ่งหมายความว่าตามตัวอย่างก่อนหน้าของเราsed
จะP
rint 1
to 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