don, çoğu durumda daha iyi olabilir, ancak dosyanın gerçekten büyük olması ve büyük sedbir komut dosyası (5000'in üzerinde komut satırında olabilir) ile baş edememeniz durumunda , işte düz 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'
Bu girişte sürgülü pencere denilen bir örnek . Bu bir inşa ederek çalışır ileriye bakma ait tampon $Bhiç bir şey yazdırmak için çalışmadan önce -count hatları.
Ve aslında, muhtemelen daha önceki noktamı açıklığa kavuşturmalıyım: Hem bu çözüm hem de Don’lar için birincil performans sınırlayıcısı doğrudan aralıklarla ilgili olacak. Bu çözelti, daha büyük bir aralık ile yavaş olacak boyutlarda don en büyük aralığı ile yavaş olacak ise, frekans . Başka bir deyişle, giriş dosyası çok büyük olsa bile, gerçek aralık oluşumu hala çok nadirse, o zaman çözümü muhtemelen yoludur. Ancak, aralık büyüklüğü nispeten yönetilebilir ve sık sık meydana gelmesi muhtemelse, seçmeniz gereken çözüm budur.
İşte iş akışı:
- Eğer
$matchbir öncesinde desen uzayda bulunan \newline, sedyinelemeli olacak Dher elete \newline olduğunu ilerlettiği o.
$match'Nin kalıp alanını daha önce tamamen temizledim - fakat çakışmayı kolayca idare etmek için bir dönüm noktası bırakmak çok daha iyi çalışıyor gibi görünüyor.
- Aynı zamanda
s/.*\n.*\($match\)/\1/bir seferde onu almaya çalışarak döngüyü atlatmaya çalıştım , ancak $A/$Bbüyük olduğunda Dseçkin döngü önemli ölçüde daha hızlı oluyor.
- Sonra, ewline sınırlayıcısının
Nönündeki girişin ext satırını \nçekeriz ve en son kullanılan w / w düzenli ifademize başvurarak Dbir /\n.*$match/kez daha seçmeye çalışırız //.
- Desen alanı eşleşirse
$match, bunu yalnızca $matchçizginin başında yapabilir - tüm $Before çizgiler temizlenir.
- Böylece daha
$Asonradan döngü başlıyoruz .
- Bu döngünün her koşmak biz deneriz
s///için yerini tutmaz &kendisi $Ainci \ndesen uzayda ewline karakterini ve başarılı olursa, tbizim bütün ve - est bizi dala ayrılacak $Atamamen üstten üzerinde senaryoyu başlatmak için komut dosyası dışarı - fter tamponunu eğer varsa bir sonraki giriş hattında.
- Eğer
test başarılı olmazsa b, :top etiketine geri döneceğiz ve başka bir girdi satırı için tekrar elde edeceğiz - muhtemelen daha sonra $matchtoplama yapılırsa döngü $Abaştan başlar.
- Biz geçmiş olsun
$matchfonksiyon döngü, o zaman çalışacağım pRint $eğer bu bunu ise son satırı ve !etmeye s///yönelik yerini tutmaz &kendisi $Binci \ndesen uzayda ewline karakteri.
- Bunu da
ttahmin edeceğiz ve eğer başarılı olursa :Print etiketine geçeceğiz .
- Olmazsa op'a geri dönelim
:tve arabelleğe başka bir giriş satırı ekleyelim.
- Biz yaparsak o kadar
:Pbiz edeceğiz Rint Psonra Rint Dilk kadar elete \ndesen uzayda ewline ve kalanları ile üstten senaryoyu yeniden çalıştırın.
Ve bu sefer, eğer yapıyor olsaydık A=2 B=2 match=5; seq 5 | sed...
:PRint'deki ilk yineleme için kalıp alanı şöyle görünür:
^1\n2\n3$
Ve bu sed, $Before arabelleğini böyle toplar . Ve böylece topladığı girdinin arkasındakised çıktı- $Bsayı satırlarına yazdırır . Daha önceki örnekte verilen bu araçlar, olur rint çıkışına ve sonra elete o ve senaryonun üstüne gibi hangi görünüyor desen alanını geri göndermek:sedP1D
^2\n3$
... ve betiğin üstünde Next giriş satırı alınır ve bir sonraki yineleme şöyle görünür:
^2\n3\n4$
Ve 5girişin ilk oluşumunu bulduğumuzda , desen alanı aslında şöyle görünür:
^3\n4\n5$
Sonra Dseçkin döngü devreye girer ve içinden geçtiğinde şöyle görünür:
^5$
Ve ne zaman Next giriş hattı çekilir sedhit EOF ve sonlandırılıyor. O zamana kadar sadece P1. ve 2. satırları değiştirdi.
İşte bir örnek çalışma:
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'
Bu yazdırır:
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