Bunun yerine awk kullanılabilir mi?


17

Numarayı buradan ratingçıktı olarak almak istiyorum

# nc localhost 9571 
language:
language:en_ZA.UTF-8
language:en_ZW.UTF-8
session-with-name:Ubuntu Classic (No effects):gnome-session --session=2d-gnome
session-with-name:Ubuntu (Safe Mode):gnome-session -f --session=2d-gnome
session-with-name:Ubuntu Classic:gnome-session --session=classic-gnome
xsession:/etc/X11/Xsession
rating:94

Böyle yapabilirim

# nc localhost 9571 | grep rating | cut -d: -f2
94

ancak awkbunun yerine daha basit bir çözüm için kullanılabilir mi?


Bu soru konu dışı gibi görünüyor çünkü Awk arayüzünde programlama ile ilgili ve StackOverflow.com
Magellan

Yanıtlar:


32
$ nc localhost 9571 | awk -F: '/rating/ { print $2 }'

7
Alan değerlerinden veya adlardan herhangi biri "derecelendirme" dizesini içeriyorsa, yani oturum adlarından birinde "derecelendirme" kelimesi varsa yanlış sonuçlar verebilir. Daha iyi:awk -F: '$1 == "rating" {print $2}'
Ingmar Hupp

3
Ya da belki awk -F: '/^rating:/ { print $2 }'?
CVn

Bunu biliyorum, ama OP komutuna dayanarak dönüşüyorum.
quanta

@IngmarHupp Aynı şeyi düşündüm. Aslında, bu değişiklikle cevabı düzenlediğim söz konusu kayıtla tam olarak eşleşmek çok daha iyi. Bu, insanların awk'yi daha etkili kullanmayı öğrenmelerine yardımcı olacaktır.
Dan Moulding

14

Quanta beni dövdü, ama sedeğer bu şekilde eğilimliysen bir varyant ekleyeceğim :

nc localhost 9571 | sed -ne 's/^rating://p'

Yine de MadHatter'in söylediği şey. Mevcut çözümünüz mükemmel ses. (Sadece istediğiniz "^rating:"satırı almanızı sağlamak için sadece kelimeden ziyade grep olsam da .)


Çok seviyorum sed! Çok az ve değersizdir ...
Mei

9

Kabuğu da kullanabilirsiniz:

nc localhost 9571 | 
while IFS=: read key val; do [[ $key = "rating" ]] && echo "$val"; done

Bu en hızlı yoldur - ve ötesinde herhangi bir işlemin ortaya çıkmasını önler nc. Güzel!
Mei

7

evet, grep ve cut yerine iki tane awk kullanabilirsiniz (ve kullanmalısınız):

$ nc localhost 9571 | awk -F: '/^rating:/ { print $2 }'

Çirkin hataları önlemek için mümkün olduğunca iyi bir çizgi eşleştirdiğinizden emin olun.

  • /rating/ İşler,
  • /^rating/ daha iyi (daha güvenli),
  • /^rating:/ en iyisidir (bu durumda).

4

Bu olabilir:

nc localhost 9571  | awk -F: '{ if ($1 == "rating") print $2 }' 

(Yukarıdaki localhost ile ne yaptığınızı bilmiyorum, bu yüzden çıktınızı awk komutuma girdi olarak kullandım, sonra "cat" yerine "nc ..." yazdı - ama iyi olmalı.)

Ama bunu neden yaptın? UNIX yolu , her biri bir şeyi iyi yapan, daha büyük çok işlevli araçlar kullanmak yerine boru hatları ile birbirine bağlanmış çok sayıda küçük araca sahip olmaktır. Tek bir eşleşen çizgi seçmeniz gerekir, buradan bir alan seçin: grepeşleşmeli satırları cutseçer ve giriş satırlarından alanları seçer; görev için mükemmeller. Ama gerçekten hepsi bir arada awk ile yapmak istiyorsanız, işte gidiyorsunuz.


Bunun bir nedeni, kullanmak grepve cutiki işlemin ortaya çıkmasını gerektirir ve awk(veya sed) kullanmak yalnızca bir işlem gerektirir. Bir sürecin ortaya çıkması hesaplama açısından pahalıdır. Ayrıca, perlveya ruby(et al) kullanmanın aksine sedve awkçok daha hafiftir.
Mei

2
Yeterince adil, ancak (F15) sistemimdeki awk ikili boyutunun 360948 bayt olduğunu, grep ve cut ikili dosyaların birlikte 170824 olduğunu not ediyorum. İkili diskten kurtulmak için. Dürüst olmak gerekirse, bu düşüncelerin herhangi birinin modern sistemler için önemli olduğundan şüphe ediyorum, ancak en aza indirmeye karar verirseniz, işte gidiyorsunuz!
MadHatter

Foo Bah: düzenleme teklifiniz için teşekkürler, ancak quanta, benim önerimden daha akıcı bir şekilde benimkinden daha sonra bir yayın yaptı. Benimkini tercih ettim, çünkü giriş seviyesi bir awk kullanıcısının nasıl çalıştığını görmesi daha kolay ve bu nedenle düzenlemenizi reddetti. Düşünce için teşekkürler!
MadHatter

3

Quanta'nın cevabı en kolay ve ben de yazacağım olsa da, eminim GNU awk (gawk) ' nun da ağ oluşturabileceğini bilmiyordunuz ? Gerçekten isterseniz, her şeyi awk ile yazabilirsiniz:

BEGIN {
    FS = ":"
    f = "/inet/tcp/0/127.0.0.1/9571"
    while ((f |& getline) > 0)
        if ($1 ~ /^rating$/) {print $2}
}

Bir sunucuda nc yüklü değilse, nc izinleri kısıtlıysa veya awk'ı gerçekten seviyorsanız bu yararlı olabilir.


Oooh. Güzel. Ağ oluşturma ve yeniden işleme örneği.
Dr. Edward Morbius

0

Ayrıca sed kullanabilirsiniz,

nc localhost 9571 | sed -n "s/^rating:\([\d]*\)/\1/p"

Bu, "derecelendirmenin" satırı başlatmasını ve rakamların rating:


0

Perl bir seçenekse:

nc localhost 9571 | perl -F: -lane 'print $F[1] if /rating/'

-aautosplits içine her satır @Fdizisi
-F:kullanımları :alan ayırıcı olarak yerine boşluk varsayılan
/rating/regex bulunursa eğer doğruysa getiri
$F[1]2. unsurdur @Fdizisi.
Perl dizileri 0 öğesi ile başlarken awk 1 $ ile başlar

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.