Sana katılıyorum olur - bu muhtemelen olan genel bir sorun. Bununla birlikte, bazı yaygın yardımcı programların, onu işlemek için bazı olanakları vardır.
nl
nlörneğin, girdiyi mantıksal sayfalara-d iki karakterli bir bölüm sınırlayıcı tarafından kaldırıldığı şekilde ayırır . Bir çizgide tek başına üç tekrar, bir başlığın başlangıcını gösterir , iki gövde ve bir altbilgi . Girişte bulunan bunlardan herhangi birini çıktıdaki boş bir satırla değiştirir - yazdırdığı tek boş satırdır
Örneğinizi başka bir bölüm içerecek şekilde değiştirdim ve yerleştirdim ./infile. Yani şöyle görünüyor:
line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D
@@start
line M
line N
line O
@@end
Sonra aşağıdakileri çalıştırdım:
sed 's/^@@.*start$/@@@@@@/
s/^@@.*end$/@@/' <infile |
nl -d@@ -ha -bn -w1
nlmantıksal sayfalarda durumu biriktirdiği söylenebilir , ancak varsayılan olarak değildir. Bunun yerine, girdisinin çizgilerini stillere ve bölümlere göre numaralandıracaktır . Yani -ha, tüm başlık satırlarını saymak ve bir vücut durumunda başladığı için hiçbir vücut çizgisi-bn anlamına gelmez .
Bunu öğrenene kadar nlherhangi bir girdi için kullanıyordum , ancak nlbunun varsayılan -delimiter'e göre çıktıyı bozabileceğini fark ettikten sonra \:, ona daha dikkatli olmayı öğrendim ve grep -nF ''bunun yerine test edilmemiş girdi için kullanmaya başladım . Ancak o gün öğrenilen bir başka ders nl, sedyukarıdaki gibi sadece girişini biraz değiştirirseniz - bu gibi - diğer açılardan çok yararlı bir şekilde uygulanabileceğiydi .
ÇIKTI
line A
line B
1 line X
2 line Y
3 line Z
line C
line D
1 line M
2 line N
3 line O
İşte biraz daha nl- numaralandırılmışlar dışındaki tüm satırların boşlukla nasıl başladığını yukarıda fark ettiniz mi? Tüm nlsayılar hatları her kafasının içine karakter belirli sayıda ekler. Bu satırlar için numaralandırılmaz - boşluklar bile - numarasız satırların başına (idth -wcount + -separator len) * boşlukları ekleyerek girintiyle her zaman eşleşir . Bu, numaralandırılmamış içeriği tam olarak numaralandırılmış içerikle karşılaştırarak ve çok az çaba sarf etmenize olanak tanır. Bunun sizin nliçin mantıksal bölümlere bölüneceğini ve -ssayıladığı her satırın başına rastgele eğilimler ekleyebileceğinizi düşündüğünüzde, çıktısını işlemek oldukça kolaylaşır:
sed 's/^@@.*start$/@@@@@@/
s/^@@.*end/@@/; t
s/^\(@@\)\{1,3\}$/& /' <infile |
nl -d@@ -ha -bn -s' do something with the next line!
'
Yukarıdaki baskılar ...
line A
line B
1 do something with the next line!
line X
2 do something with the next line!
line Y
3 do something with the next line!
line Z
line C
line D
1 do something with the next line!
line M
2 do something with the next line!
line N
3 do something with the next line!
line O
GNU sed
Eğer nlhedef uygulaması değil, o bir GNU sedolabilir eBir maç bağlı için keyfi bir kabuk komutu xecute.
sed '/^@@.*start$/!b
s//nl <<\\@@/;:l;N
s/\(\n@@\)[^\n]*end$/\1/
Tl;e' <infile
Yukarıdaki sed, ikame Testini başarıyla geçip babel'e geri dönmeyi durduracak kadar desen uzayında girişi toplar :l. eYaptığında , desen alanının geri kalan kısmı için burada bir belge nlolarak gösterilen girdiyle xecutes yapar <<.
İş akışı şu şekildedir:
/^@@.*start$/!b
- Bir eğer
^tüm çizgi $yok !değil /maç /yukarıdaki kalıbı, o zaman olduğu bsenaryo dışına çiftçiliği ve autoprinted - yani bu noktadan itibaren sadece desen ile başladı çizgilerin bir dizi ile çalışıyorsanız üzerinde.
s//nl <<\\@@/
- boş
s//alan /, sedeşleştirilmeye çalışılan son adresin yerini alır - dolayısıyla bu komut tüm @@.*startsatırın nl <<\\@@yerine kullanılır.
:l;N
:Komutu bir şube etiketi tanımlar - burada bir adlandırılmış set :lHabil'i. NExt komutu bir takip desen boşluğa girişinin sonraki çizgisini ekler \newline karakteri. Bu, örüntü alanında \newline almanın birkaç yolundan biridir sed- \newline karakteri, sedbunu bir süredir yapan bir der için kesin bir sınırlayıcıdır .
s/\(\n@@\)[^\n]*end$/\1/
- bu
s///ikame ancak bir başlangıçla karşılaştıktan sonra ve yalnızca bir bitiş çizgisinin ilk takipinde başarılı olabilir . Sadece son \newline'ın hemen ardından desen alanının @@.*endsonunu işaretleyen bir desen alanı üzerinde hareket edecektir $. Hareket ettiğinde, eşleşen dizenin tamamını \1ilk \(grupla değiştirir \)veya \n@@.
Tl
TBir etiket est komut dalları (eğer varsa) , başarılı bir ikame olarak bir giriş hattı paterni boşluğa çekilmiş son kez gerçekleşmediyse (w / gibi N) . Bu \n, son sınırlayıcınızla eşleşmeyen desen alanına her bir ewline eklendiğinde, Test komutu başarısız olur ve abel'e geri döner :l, bu sedda Next satırında çekme ve başarılı olana kadar döngü ile sonuçlanır.
e
Son eşlemenin yerine koyma başarılı olduğunda ve komut dosyası başarısız bir Test için geri dönmediğinde, aşağıdakine benzer bir komutu xecute sededecektir :el
nl <<\\@@\nline X\nline Y\nline Z\n@@$
Buradaki son satırı düzenleyerek kendiniz görebilirsiniz Tl;l;e.
Yazdırır:
line A
line B
1 line X
2 line Y
3 line Z
line C
line D
1 line M
2 line N
3 line O
while ... read
Bunu yapmanın son bir yolu ve belki de en basit yolu, bir while readdöngü kullanmaktır , ancak iyi bir nedenden dolayı. Kabuk - (özellikle bir bashkabuk) - girdiyi büyük miktarlarda veya sabit akışlarla işlemede tipik olarak oldukça uçsuzdur. Bu da mantıklıdır - kabuğun görevi karakterleri karaktere göre ele almak ve daha büyük şeyleri işleyebilecek diğer komutları çağırmaktır.
Ama önemlisi onun rolü hakkında kabuk olduğunu orada olmamalıdır read bunun için belirtilen - girdinin overmuch değil o kadar çok tüketir veya eksik komutlar da çağrılar bırakılır bu süre içinde yeterince röle olmadığı noktaya giriş veya çıkışı tampon - bayta. Bu yüzden readmükemmel bir giriş testi yapar - returnkalan giriş olup olmadığı hakkında bilgi ve bunu okumak için bir sonraki komutu çağırmanız gerekir - ancak aksi takdirde genellikle en iyi yol değildir.
Bununla birlikte, senkronize olarak girişi işlemek için birinin nasıl kullanılabileceğine read ve diğer komutlara bir örnek :
while IFS= read -r line &&
case $line in (@@*start) :;; (*)
printf %s\\n "$line"
sed -un "/^@@.*start$/q;p";;
esac;do sed -un "/^@@.*end$/q;=;p" |
paste -d: - -
done <infile
Her yinelemede gerçekleşen ilk şey readbir çizgi çeker. Başarılı olursa, döngü henüz EOF'ye çarpmadığı anlamına gelir ve bu nedenle casebir başlangıç sınırlayıcıyla eşleştiğinde doblok hemen yürütülür. Else, onu printfyazdırır ve denir.$linereadsed
sedolacak pkarşılaştığı dek her satırını Rint başlangıç o zaman - işaretleyici qtamamen girişini UITS. -uNbuffered anahtarı GNU için gerekli olan sedo açgözlülükle aksi ziyade tampon, ancak çünkü - spec göre - diğer POSIX sedlar herhangi bir özel göz olmadan çalışması gerekir - bu yüzden sürece <infilenormal bir dosyadır.
İlk sed quyduğunda, kabuk , son işaretiyle karşılaşana kadar her satırı yazdıran dobaşka bir çağıran döngü bloğunu yürütür . Bu borular etmek çıkışını , onların her satırda bir satır numaralarını yazdırır çünkü. Bunun gibi:sedpaste
1
line M
2
line N
3
line O
pastedaha sonra bunları :karakterlere yapıştırır ve tüm çıktı şuna benzer:
line A
line B
1:line X
2:line Y
3:line Z
line C
line D
1:line M
2:line N
3:line O
Bunlar sadece örnektir - burada testte veya bloklarda her şey yapılabilir, ancak ilk yardımcı program çok fazla girdi tüketmemelidir.
İlgili tüm yardımcı programlar aynı girdiyi okur ve sonuçlarını kendi sırayla yazdırır. Farklı programları diğerlerinden daha tampon çünkü - - Bu tür bir şey asmak için zor olabilir ancak genellikle güvenebileceğiniz dd, headve seddoğru olanı yapmak (GNU için, gerçi sed, sen cli-şalterini gerekir) ve her zaman güvenebilmelisiniz read- çünkü doğa gereği çok yavaştır . Bu yüzden yukarıdaki döngü bunu giriş bloğu başına sadece bir kez çağırır.
nldevlet biriktirmek zorunda değildir . Bak aznl -dsizin kontrol etmek veman/infohakkında bilgi için sayfalarınlbireyin bölüm sınırlayıcı .