Sed'in eşleşmeyen satırları yoksaymasını sağlayın


94

Bir sedifadeye göre filtre eşleştirme satırlarını nasıl yapabilirim , ancak eşleşmeyen satırları yazdırmalarına izin vermek yerine yoksayabilirim?

Gerçek bir örnek olarak, scalacbir dizi dosya üzerinde çalıştırmak (Scala derleyicisini) ve -verboseçıktısından .classoluşturulan dosyaları okumak istiyorum . scalac -verbosebir sürü mesaj çıkarır, ancak biz sadece formdakilerle ilgileniyoruz [wrote some-class-name.class]. Şu anda yaptığım şey şudur ( |&bash 4.0'ın stderr'i sonraki programa aktarmanın yolu):

$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/'

Bu, ilgilendiğimiz mesajlardan dosya adlarını çıkaracak, ancak diğer tüm mesajların değişmeden geçmesine de izin verecektir! Tabii ki bunun yerine şunu yapabiliriz:

$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' |
  sed 's/^\[wrote \(.*\.class\)\]$/\1/'

Bu işe yarıyor ama gerçek problemin etrafından dolaşmaya çok benziyor, bu sedda girdiden eşleşmeyen satırları yok sayma talimatı verilecek. Peki bunu nasıl yapacağız?


2
Kabul edilen cevap mouviciel tarafından yazılan cevap olmalıdır: stackoverflow.com/a/1665574/869951
Oliver

Yanıtlar:


90

Düz sed ile başka bir yol:

sed -e 's/.../.../;t;d'

s///bir ikamedir, therhangi bir etiket olmadan koşullu olarak aşağıdaki tüm komutları atlar, dsatırı siler.

Perl veya grep'e gerek yok.

(Nicholas Riley'nin önerisi üzerine düzenlendi)


3
OS X'te 10.8.2 ı ayırmak zorunda txve dbir satır yerine ben başlamıştı olarak noktalı virgül ile undefined label 'x;d;:x'.
davidchambers

6
Daha da iyisi: sed -e 's/.../.../' -e 'tx' -e 'd' -e ':x'( benzer bir soruya yapılan bir yorumda önerildi ).
davidchambers

1
Hiçbir etiketi sağlandı ise 't', yani daha basit komut sonuna aktaracaktır: sed -e 's/.../.../' -e 't' -e 'd'.
Nicholas Riley

İnsanlar -eseçeneğin anlamını bilmiyorlar, bu yüzden genel olarak bundan bahsetmeyin.
Fredrick Gauss

246

Eşleşmeyen satırları yazdırmak istemiyorsanız, kombinasyonunu kullanabilirsiniz.

  • -n sed'e yazdırmamasını söyleyen seçenek
  • p sed'e eşleşeni yazdırmasını söyleyen bayrak

Bu şunu verir:

sed -n 's/.../.../p'

3
Bu yaklaşımın bir dezavantajı, eşleşen birden çok ifadeniz varsa, sonucun birden çok kez yazdırılacağıdır. Örneğin: echo foo | sed -n -e 's/foo/bar/p' -e 's/bar/oof/p'olacak hem de çıktı barve oofayrı satırlarda. Her ne kadar goto-etiket çeşitliliği birden fazla kalıbı işleyemez, çünkü ilk kalıp eşleşmezse satırı silecektir.
Rapsey

@Rapsey, çünkü ona iki kez yazdırmasını söylüyorsunuz. Tek sed komutunda, ona iki kez yazdırmasını söylediniz, her örnek yerinde yazdırılır (veya belki arabelleğe alınır). Ya -e yerine pipo yapmanız gerekir ya da son -e'ye sadece 'p' koyarsınız.
mikrobiyal

@Rapsey: Bu konuyla ilgili
cevabımı görün

@microbial, son p bayrağı , son ikame ifadesiyle eşleşen her satırda çalışacağından çalışmaz .
Amessihel

1

Perl kullanın:

... |& perl -ne 'print "$1\n" if /^\[wrote (.*\.class)\]$/'

0

Rapsey, çoklu ikame ifadeleri hakkında alakalı bir noktaya değindi.

  • İlk olarak, bir Unix SE cevabından alıntı yaparak , "çoğu sed komutunun önekini uyguladıkları satırları sınırlandırmak için bir adresle" önekleyebilirsiniz.
  • İkinci olarak, komutları küme ayraçları içinde gruplayabilirsiniz {}( noktalı virgülle ;veya yeni bir satırla ayrılmış olarak )
  • Üçüncüsü, son değiştirmeye p yazdırma bayrağını ekleyin

Sözdizimi:

sed -n -e '/^given_regexp/ {s/regexp1/replacement1/flags1;[...];s/regexp1/replacement1/flagsnp}'

Örnek ( daha fazla ayrıntı için Buradaki belgeye bakın):

  • Kod:

    sed -n -e '/^ha/ {s/h/k/gp;s/a/e/g}' <<SAMPLE
    haha
    hihi
    SAMPLE
    
  • Sonuç:

    kaka
    

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.