don có thể tốt hơn trong hầu hết các trường hợp, nhưng chỉ trong trường hợp tệp thực sự lớn và bạn không thể sedxử lý tệp tập lệnh lớn (có thể xảy ra ở khoảng 5000+ dòng script) , ở đây rõ ràng là 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'
Đây là một ví dụ về cái được gọi là cửa sổ trượt trên đầu vào. Nó hoạt động bằng cách xây dựng bộ đệm nhìn về phía trước của các $Bdòng -count trước khi cố gắng in bất cứ thứ gì.
Và trên thực tế, có lẽ tôi nên làm rõ quan điểm trước đây của mình: bộ giới hạn hiệu suất chính cho cả giải pháp này và don sẽ liên quan trực tiếp đến khoảng thời gian. Giải pháp này sẽ chậm với kích thước khoảng lớn hơn , trong khi don sẽ chậm với tần số khoảng lớn hơn . Nói cách khác, ngay cả khi tệp đầu vào rất lớn, nếu khoảng thời gian thực tế xảy ra vẫn không thường xuyên thì giải pháp của anh ta có lẽ là cách để đi. Tuy nhiên, nếu kích thước khoảng tương đối dễ quản lý và có khả năng xảy ra thường xuyên, thì đây là giải pháp bạn nên chọn.
Vì vậy, đây là quy trình công việc:
- Nếu
$matchđược tìm thấy trong không gian mẫu có trước một \newline, sedsẽ bỏ qua đệ quy Dmọi \newline trước nó.
- Tôi đã xóa
$matchhoàn toàn không gian mô hình trước đó - nhưng để dễ dàng xử lý sự chồng chéo, để lại một dấu mốc dường như hoạt động tốt hơn nhiều.
- Tôi cũng đã cố
s/.*\n.*\($match\)/\1/gắng để có được nó trong một lần và tránh vòng lặp, nhưng khi $A/$Blớn, Dvòng lặp elete chứng tỏ nhanh hơn đáng kể.
- Sau đó, chúng tôi kéo vào
Ndòng mở rộng của đầu vào trước \ndấu phân cách ewline và thử lại một lần nữa để xóa Dmột /\n.*$match/lần nữa bằng cách tham khảo biểu thức chính quy được sử dụng gần đây nhất của chúng tôi w / //.
- Nếu không gian mẫu khớp với nhau
$matchthì nó chỉ có thể làm như vậy $matchở đầu dòng - tất cả các $Bdòng eFor đã bị xóa.
- Vì vậy, chúng tôi bắt đầu vòng lặp qua
$After.
- Mỗi lần chạy của vòng lặp này, chúng tôi sẽ cố gắng
s///ubstitute cho &bản thân những $Athứ \nvật ewline trong không gian mô hình, và nếu thành công, test sẽ chi nhánh chúng tôi - và cả chúng tôi $Ađệm fter - ra của kịch bản hoàn toàn để bắt đầu kịch bản lại từ đầu với dòng đầu vào tiếp theo nếu có.
- Nếu
test không thành công, chúng tôi sẽ bquay lại :tnhãn op và lặp lại cho một dòng đầu vào khác - có thể bắt đầu vòng lặp nếu $matchxảy ra trong khi thu thập $After.
- Nếu chúng ta vượt qua một
$matchvòng lặp chức năng, sau đó chúng tôi sẽ cố gắng print những $dòng cuối cùng nếu điều này là nó, và nếu !không cố gắng để s///ubstitute cho &bản thân những $Bthứ \nvật ewline trong không gian mô hình.
- Chúng tôi cũng sẽ đánh giá
tđiều này và nếu thành công, chúng tôi sẽ phân nhánh :Pnhãn rint.
- Nếu không, chúng tôi sẽ phân nhánh trở lại
:top và nhận một dòng đầu vào khác được thêm vào bộ đệm.
- Nếu chúng ta làm cho nó để
:Print chúng tôi sẽ Print sau đó Delete lên đến đầu tiên \newline trong không gian mô hình và chạy lại kịch bản từ đầu với những gì còn lại.
Và vì vậy lần này, nếu chúng ta đang làm A=2 B=2 match=5; seq 5 | sed...
Không gian mẫu cho lần lặp đầu tiên tại :Print sẽ trông như sau:
^1\n2\n3$
Và đó là cách sedtập hợp $Bbộ đệm e ấp của nó . Và do đó, sedin ra $Bcác dòng -count đằng sau đầu vào mà nó đã thu thập. Điều này có nghĩa rằng, cho ví dụ trước của chúng tôi, sedsẽ Print 1đến đầu ra, và sau đó Delete đó và gửi lại để phía trên cùng của kịch bản một không gian mô hình mà trông giống như:
^2\n3$
... và ở đầu tập lệnh, Ndòng đầu vào ext được lấy ra và do đó lần lặp tiếp theo trông như sau:
^2\n3\n4$
Và do đó, khi chúng ta tìm thấy sự xuất hiện đầu tiên của 5đầu vào, không gian mẫu thực sự trông như sau:
^3\n4\n5$
Sau đó, Dvòng lặp elete khởi động và khi nó đi qua, nó trông giống như:
^5$
Và khi Ndòng đầu vào ext được kéo, sedchạm EOF và thoát. Vào thời điểm đó, nó chỉ có Pcác dòng 1 và 2.
Đây là một ví dụ chạy:
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'
Đó là bản in:
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