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ể sed
xử 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 $B
dò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 \n
ewline, sed
sẽ bỏ qua đệ quy D
mọi \n
ewline trước nó.
- Tôi đã xóa
$match
hoà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/$B
lớn, D
vòng lặp elete chứng tỏ nhanh hơn đáng kể.
- Sau đó, chúng tôi kéo vào
N
dòng mở rộng của đầu vào trước \n
dấu phân cách ewline và thử lại một lần nữa để xóa D
mộ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
$match
thì nó chỉ có thể làm như vậy $match
ở đầu dòng - tất cả các $B
dòng eFor đã bị xóa.
- Vì vậy, chúng tôi bắt đầu vòng lặp qua
$A
fter.
- 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 $A
thứ \n
vật ewline trong không gian mô hình, và nếu thành công, t
est 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
t
est không thành công, chúng tôi sẽ b
quay lại :t
nhã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 $match
xảy ra trong khi thu thập $A
fter.
- Nếu chúng ta vượt qua một
$match
vòng lặp chức năng, sau đó chúng tôi sẽ cố gắng p
rint 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 $B
thứ \n
vậ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 :P
nhãn rint.
- Nếu không, chúng tôi sẽ phân nhánh trở lại
:t
op 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ó để
:P
rint chúng tôi sẽ P
rint sau đó D
elete lên đến đầu tiên \n
ewline 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 :P
rint sẽ trông như sau:
^1\n2\n3$
Và đó là cách sed
tập hợp $B
bộ đệm e ấp của nó . Và do đó, sed
in ra $B
cá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, sed
sẽ P
rint 1
đến đầu ra, và sau đó D
elete đó 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, N
dò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 đó, D
vòng lặp elete khởi động và khi nó đi qua, nó trông giống như:
^5$
Và khi N
dòng đầu vào ext được kéo, sed
chạm EOF và thoát. Vào thời điểm đó, nó chỉ có P
cá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