Kann awk stattdessen verwendet werden?

17

Ich möchte die Nummer ratingals Ausgabe von diesem bekommen

# 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

Ich kann es so machen

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

könnte awkaber stattdessen für eine einfachere lösung verwendet werden?

Sandra
quelle
Diese Frage scheint nicht zum Thema zu gehören, da es um die Programmierung in der Awk-Benutzeroberfläche geht und
Magellan,

Antworten:

32
$ nc localhost 9571 | awk -F: '/rating/ { print $2 }'
Quanten
quelle
7
Kann zu falschen Ergebnissen führen, wenn einer der Feldwerte oder -namen die Zeichenfolge "Bewertung" enthält, dh einer der Sitzungsnamen das Wort "Bewertung" enthält. Besser:awk -F: '$1 == "rating" {print $2}'
Ingmar Hupp
3
Oder vielleicht doch awk -F: '/^rating:/ { print $2 }'?
ein Lebenslauf
Ich weiß das, aber ich konvertiere auf der Grundlage des OP-Befehls.
Quanten
@IngmarHupp Ich dachte genau das gleiche. Es ist in der Tat so viel besser, auf den genauen fraglichen Datensatz abzustimmen, dass ich die Antwort mit dieser Änderung bearbeitet habe. Dies wird hoffentlich dazu beitragen, dass Menschen lernen, awk effektiver zu nutzen.
Dan Moulding
14

Quanta hat mich geschlagen, aber ich werde eine sedVariante hinzufügen, wenn Sie so geneigt sind:

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

Das Gleiche wie MadHatter. Ihre aktuelle Lösung ist einwandfrei. (Obwohl ich "^rating:"eher nach als nur nach dem Wort greifen würde, um sicherzustellen, dass Sie nur die Zeile erhalten, die Sie möchten.)

SmallClanger
quelle
Ich Liebe sed! Es ist so nicht ausgelastet und unterschätzt ...
Mei
9

Sie können auch einfach die Shell verwenden:

nc localhost 9571 | 
while IFS=: read key val; do [[ $key = "rating" ]] && echo "$val"; done
Glenn Jackman
quelle
Dies ist der schnellste Weg - und verhindert, dass darüber hinausgehende Prozesse entstehen nc. Nett!
Mei
7

Ja, Sie können (und sollten) (eine) awk anstelle von (zwei) grep und cut verwenden:

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

Achten Sie darauf, dass Sie Ihre Linie so gut wie möglich zusammenbringen, um hässliche Fehler zu vermeiden.

  • /rating/ arbeitet,
  • /^rating/ ist besser (sicherer),
  • /^rating:/ ist am besten (in diesem Fall).
Michał Šrajer
quelle
4

Es kann:

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

(Ich weiß nicht, was Sie mit localhost oben machen. Verwenden Sie also Ihre Ausgabe als Eingabe für meinen awk-Befehl und ersetzen Sie dann die "cat" durch "nc ..." - aber es sollte in Ordnung sein.)

Aber warum würdest du das tun? Die UNIX-Methode besteht darin, viele kleine Werkzeuge zu haben, von denen jedes eine Sache gut macht und die über Pipelines aneinandergereiht sind, anstatt größere Multifunktionswerkzeuge zu verwenden. Sie müssen eine einzelne übereinstimmende Zeile auswählen und ein Feld daraus auswählen: grepWählt Zeilen mit Übereinstimmungen aus und cutwählt Felder aus Eingabezeilen aus; Sie sind perfekt für die Aufgabe. Aber wenn Sie wirklich alles in einem mit awk machen wollen, dann können Sie loslegen.

MadHatter unterstützt Monica
quelle
Ein Grund dafür ist, dass für die Verwendung von grepund das cutStarten von zwei Prozessen und für die Verwendung von awk(oder sed) nur einer erforderlich ist. Das Starten eines Prozesses ist rechenintensiv. Auch im Gegensatz zu perloder ruby(et al), sedund awksind viel leichter vorne.
Mei
2
Fair genug, obwohl ich bemerke, dass die Größe der awk-Binärdatei auf meinem (F15) -System 360.948 Bytes beträgt, während die Binärdateien grep und cut zusammen 170824 sind. Weniger Zyklen mit nur einem Fork + Exec, aber mehr Speicher und mehr E / A um die binäre off disc zu bekommen. Ehrlich gesagt, ich bezweifle, dass eine dieser Überlegungen für moderne Systeme von Bedeutung ist, aber wenn Sie minimieren möchten, können Sie loslegen!
MadHatter unterstützt Monica
Foo Bah: Danke für deinen Bearbeitungsvorschlag, aber quanta hat einen späteren Beitrag als meinen verfasst, der noch rationaler ist als dein Vorschlag. Ich habe meine vorgezogen, weil es für einen einsteigenden awk-Benutzer einfacher ist, zu sehen, wie es funktioniert, und daher Ihre Bearbeitung abgelehnt hat. Vielen Dank für den Gedanken!
MadHatter unterstützt Monica
3

Obwohl die Antwort von Quanta die einfachste ist und die, die ich auch schreiben würde, wette ich, dass Sie nicht wussten, dass GNU awk (gawk) auch Networking kann ? Sie können das Ganze mit awk schreiben, wenn Sie wirklich wollen:

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

Dies kann nützlich sein, wenn auf einem Server nc nicht installiert ist, nc eingeschränkte Zugriffsrechte hat oder wenn Sie awk einfach wirklich mögen.

Mark McKinstry
quelle
Oooh. Nett. Vernetzung und ein Coprozessor-Beispiel.
Dr. Edward Morbius
0

Sie können auch sed verwenden,

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

Dadurch wird sichergestellt, dass die Zeile mit "Bewertung" beginnt und die Ziffern dem folgen rating:

Sirch
quelle
0

Wenn Perl eine Option ist:

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

-aDas automatische Aufteilen jeder Zeile in das @FArray
-F:wird :als Feldtrennzeichen verwendet. Statt des Standardwerts für Whitespace wird
/rating/true zurückgegeben, wenn Regex als zweites
$F[1]Element des @FArrays gefunden wird.
Perl-Arrays beginnen mit Element 0, während awk mit $ 1 beginnt

Chris Koknat
quelle