Eşleşen bir kalıptan sonra çizginin sadece kısmını döndür


109

Böylece bir dosyayı açarak catve ardından grepeşleşen satırları almak için kullanmak , yalnızca uğraştığım belirli günlük kümesinde çalıştığım zaman beni alır. Çizgileri bir kalıpla eşleştirmek için bir yol gerekir, ancak yalnızca çizginin bir kısmını maçtan sonra döndürmek için. Maçtan önceki ve sonraki bölüm sürekli değişecektir. sedVeya ile oynadım awk, ancak maçtan önce parçayı silmek için hattın nasıl filtrelendiğini veya sadece maçtan sonra parçayı geri döndürecek şekilde nasıl filtre edeceğimi çözemedim. Bu, filtrelemem gereken bir çizgi örneği:

2011-11-07T05:37:43-08:00 <0.4> isi-udb5-ash4-1(id1) /boot/kernel.amd64/kernel: [gmp_info.c:1758](pid 40370="kt: gmp-drive-updat")(tid=100872) new group: <15,1773>: { 1:0-25,27-34,37-38, 2:0-33,35-36, 3:0-35, 4:0-9,11-14,16-32,34-38, 5:0-35, 6:0-15,17-36, 7:0-16,18-36, 8:0-14,16-32,34-36, 9:0-10,12-36, 10-11:0-35, 12:0-5,7-30,32-35, 13-19:0-35, 20:0,2-35, down: 8:15, soft_failed: 1:27, 8:15, stalled: 12:6,31, 20:1 }

İhtiyacım olan kısım "durduktan" sonra her şey.

Bunun arkasındaki arka plan, bir şeyin ne kadar sıklıkla durduğunu bulabilmemdir:

cat messages | grep stalled | wc -l

Yapmam gereken, belirli bir düğümün kaç kez durduğunu bulmak ("durduktan" sonra her iki kolonun önündeki kısımla belirtilir). bana yardım etmeyen tezgah yok, sadece bırakılan kısmı filtrelemem gerekiyor, böylece o zaman durmuş olanlardan belirli bir düğümü bulabilirim.

Tüm amaç ve amaçlar için bu, standart GNU çekirdek araçlarına sahip bir freebsd sistemidir, ancak yardımcı olmak için fazladan bir şey yükleyemiyorum.


@Gilles, Odd aradığımda nasıl ortaya çıkmadı, sonunda kullandığım başlığı kullanmasam da ... başlığımın altındaki ekranda görünmedi. Her neyse, bu bir yana, bu beni istediğim yere götürebilir, ancak maçtan sonra tüm çizgiye ihtiyacım olsa da, ilk kelimeye değil - çok fazla değişiklik yapmayabilirim.
MaQleod

Başlığı emildi. Ben seninkini çaldım ki bu çok hoş. Al sedçözümü ve özel olarak boşluk tedavi etmiyoruz.
Gilles

@Gilles, bu nasıl yapacağımı tam olarak bilmediğim bir şey. Hala sed öğreniyorum.
MaQleod


1
@ shaa0601 Sorunuzu anlamıyorum, yorum yapmayan bir yorumda özellikle biçimlendirmek zor. Yeni, kendine yeten bir soru sor.
Gilles

Yanıtlar:


141

Bunun için kurallı araç olurdu sed.

sed -n -e 's/^.*stalled: //p'

Detaylı açıklama:

  • -n varsayılan olarak hiçbir şey yazdırmamak anlamına gelir.
  • -e bir sed komutu ile takip edilir.
  • s kalıp değiştirme komutu.
  • Normal ifade ^.*stalled:, aradığınız forma, artı önceki .*herhangi bir metne ^eşleşir (eşleşmenin satırın başlangıcında başladığını söyleyen bir metne sahip herhangi bir metin anlamına gelir ). Eğer unutmayın stalled:hattında birkaç kez oluşur bu son örneğini eşleşir.
  • Eşleşme, yani satırdaki her şey stalled:, boş dizeyle değiştirilir (yani silinir).
  • Son polarak dönüştürülmüş çizgiyi yazdırmak için araçlar.

Eşleşen kısmı korumak istiyorsanız, bir geri referans kullanın: \1yedek parça \(…\), modeldeki bir grubun içinde ne olduğunu gösterir . Burada, stalled:yedek parçaya tekrar yazabilirsiniz ; Bu özellik, aradığınız desen basit bir dizgiden daha genel olduğunda kullanışlıdır.

sed -n -e 's/^.*\(stalled: \)/\1/p'

Bazen çizginin maçtan sonraki kısmını kaldırmak isteyebilirsiniz. Desenin .*$sonuna dahil ederek ( .*satırın sonunda gelen herhangi bir metin) maça dahil edebilirsiniz $. Bu bölümü değiştirilen metinde referans verdiğiniz bir gruba koymazsanız, satırın sonu çıktıda olmaz.

Grupların ve geri referansların daha ayrıntılı bir gösterimi olarak, bu komut maçtan önceki kısmı ve maçtan sonraki kısmı değiştirir.

sed -n -e 's/^\(.*\)\(stalled: \)\(.*\)$/\3\2\1/p'

İlk iki örneği denedim ve sanki takılıyor gibi görünüyor. Hata mesajı alamıyorum, ne de yeni bir istemi alamıyorum, hiçbir şey.
MaQleod

2
@ MaQleod Oh, yönlendirmediniz, çünkü burada terminal olan standart girişte girdi bekliyor. Burada sed … <messagesbir dosyadan veri işlemek istediğiniz için giriş yönlendirmesi yaparsınız . Başka bir komutun ürettiği verileri temel alarak hareket etmek için bir boru kullanmak: somecommand | sed ….
Gilles

1
sağ, gün sonunda karartma var. komut mükemmel çalışıyor, teşekkürler.
MaQleod

1
Şimdiye kadar gördüğüm en iyi sed açıklama - teşekkürler!
Jon Wadsworth

1
@ungalcrys Neyin daha kısa versiyonu? Bu, cevabımdaki komutların hiçbirine denk değil. Ben yazmayı öneriyoruz sed 's/^.*stalled//'beri -rLinux özeldir ve böyle MacOS gibi diğer sistemlerde çalışmaz ve burada bunun herhangi bir fayda elde edilmez.
Gilles

72

Zaten kullandığınız diğer kurallı araç grep:

Örneğin:

grep -o 'stalled.*'

Gilles'un ikinci seçeneğiyle aynı sonuca sahiptir:

sed -n -e 's/^.*\(stalled: \)/\1/p'

-oBayrak döner --only-matchingtabii - - normal olarak grep'in tarafından yapılan ifadenin bir kısmı, böyle değildir tüm çizgi.

"Stalled:" ı çıktıdan çıkarmak için üçüncü bir kurallı araç kullanabiliriz:

grep -o 'stalled.*' | cut -f2- -d:

cutKomutu, ayırıcı kullanan :sonuna kadar ve baskılar alanını 2. Elbette tercih meselesi, ancak cuthatırladığım çok kolay sözdizimi.


1
-oSeçeneği belirttiğiniz için teşekkür ederiz ! Bunun yeni satırı greptanımadığını belirtmek istedim \n, bu nedenle ilk örneğiniz yalnızca ilk nkarakterle eşleşiyor . Örneğin echo "Hello Anne" | grep -o 'A[^\n]*', dizeyi döndürür A. Ancak, echo "Hello Anne" | grep -o 'A.*'beklenen döner Anneberi, .yeni satır dışında herhangi bir karakterle eşleşir.
adamlamar

1
cutSınırlayıcının çevresindeki tırnakların -d':'@poige ile kaldırıldığını unutmayın. Alıntılar ile hatırlamayı daha kolay buluyorum, örneğin -d' 'veya ile -d';'.
Anne van Rossum,

Bulgunuza göre tırnak işaretleri ile birlikte kullanmayı hatırlamak daha kolay olmalı -f 2. Cidden, neden olmasın?
poige

Çünkü, bir kolondan ;ziyade bir yarı-kolon gibi bir sınırlayıcı :belirtilmezse farklı bir şekilde yorumlanacaktır. Tabii ki bu mantıklı davranış, ama yine de kas hafızasına güvenmeyi seviyorum. Sınırlayıcıya bir kez alıntı yapmayı sevmiyorum, diğer zaman değil. Daha önce söylediğim gibi sadece kişisel tercih: hatırlaması daha kolay.
Anne van Rossum

Bir parçası .*gerekli olan süre benim için iyi çalıştı: cat filename | grep 'Return only this line xyz text' | grep -o 'xyz.*' dönerxyz text
ron

4

Ben kullanılan ifconfig | grep eth0 | cut -f3- -d:bu almak

    [root@MyPC ~]# ifconfig
    eth0  Link encap:Ethernet  HWaddr AC:B4:CA:DD:E6:F8
          inet addr:192.168.0.2  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:78998810244 errors:1 dropped:0 overruns:0 frame:1
          TX packets:20113430261 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:110947036025418 (100.9 TiB)  TX bytes:15010653222322 (13.6 TiB)

ve böyle görünmesini sağla

    [root@MyPC ~]# ifconfig | grep eth0 | cut -f3- -d:
    C4:7A:4D:F6:B8

2
Bu soruya cevap veriyor mu?
Stephen Rauch

1
Kullanabilirsiniz, cat /sys/class/net/*/addressayrıştırma gerekmez.
Anne van Rossum,

1

Düşündüğünüz başka bir kanonik araç awkşu satırla kullanılabilir:

awk -F"stalled" '/stalled/{print $2}' messages

Detaylı açıklama:

  • -FHat için bir ayırıcı tanımlar, yani "durmuş". Ayırıcıdan önceki $1her şey ile ve sonra gelen her şeyle ele alınır $2.
  • /reg-ex/ Eşleşen normal ifadeyi arar, bu durumda "durmuş".
  • {print $<n>}- n sütunu yazdırır. Ayırıcınız durmuş olarak tanımlandığından, durduktan sonraki her şey ikinci sütun olarak kabul edilir.
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.