Website-Suche

Erlernen von Linux-Befehlen: awk


Im Fall dieses Artikels könnte der Titel "Learning Linux Commands: awk" ein wenig irreführend sein. Und das liegt daran, dass awk mehr als ein Befehl ist, es ist eine eigenständige Programmiersprache. Sie können awk-Skripte für komplexe Operationen schreiben oder awk über die Befehlszeile verwenden. Der Name steht für Aho, Weinberger und Kernighan (ja, Brian Kernighan), die Autoren der Sprache, die 1977 gestartet wurde, daher teilt sie den gleichen Unix-Geist wie die anderen klassischen *nix-Dienstprogramme.

Wenn Sie sich an die C-Programmierung gewöhnen oder sie bereits kennen, werden Sie einige vertraute Konzepte in awk sehen, zumal das "k" in awk für dieselbe Person steht wie das "k" in K&R, der C-Programmierbibel. Sie benötigen einige Kommandozeilenkenntnisse in Linux und möglicherweise einige Skripting-Grundlagen, aber der letzte Teil ist optional, da wir versuchen werden, für jeden etwas anzubieten. Vielen Dank an Arnold Robbins für all seine Arbeit, die er in awk investiert hat.

In diesem Tutorial lernen Sie:

  • Was macht awk? Wie funktioniert das?
  • AWK Grundbegriffe
  • Erfahren Sie, wie Sie awk über Befehlszeilenbeispiele verwenden

Kennenlernen des awk-Befehls durch verschiedene Befehlszeilenbeispiele unter Linux

Was macht awk?

AWK ist ein Dienstprogramm/eine Sprache, die für die Datenextraktion entwickelt wurde. Wenn das Wort "Extraktion" Ihnen bekannt vorkommt, dann sollte es das auch, denn awk war einst Larry Walls Inspiration, als er Perl erschuf. awk wird oft mit sed verwendet, um nützliche und praktische Textmanipulationsaufgaben durchzuführen, und es hängt von der Aufgabe ab, ob Sie awk oder Perl verwenden sollten, aber auch von den persönlichen Vorlieben. Genau wie sed liest awk eine Zeile nach der anderen, führt je nach der Bedingung, die Sie ihm geben, eine Aktion aus und gibt das Ergebnis aus.

Eine der einfachsten und beliebtesten Anwendungen von awk ist das Auswählen einer Spalte aus einer Textdatei oder der Ausgabe eines anderen Befehls. Eine Sache, die ich mit awk zu tun pflegte, war, wenn ich Debian auf meinem zweiten Arbeitsplatz installierte, eine Liste der installierten Software von meinem primären Rechner zu erhalten und sie dann an aptitude weiterzuleiten. Dafür habe ich so etwas gemacht:


dpkg -l | awk ' {print $2} ' > installed

Die meisten Paketmanager bieten heute diese Möglichkeit an, zum Beispiel die -qa-Optionen von rpm, aber die Ausgabe ist mehr, als ich möchte. Ich sehe, dass die zweite Spalte der Ausgabe von dpkg -l den Namen der installierten Pakete enthält, deshalb habe ich $2 mit awk: verwendet, um nur die 2. Spalte zu erhalten.

Grundkonzepte

Wie Sie bemerkt haben, wird die Aktion, die von awk ausgeführt werden soll, in geschweifte Klammern eingeschlossen, und der gesamte Befehl wird in Anführungszeichen gesetzt. Aber die Syntax ist awk 'condition { action }'. In unserem Beispiel hatten wir keine Bedingung, aber wenn wir, sagen wir, nur nach installierten vim-bezogenen Paketen suchen wollten (ja, es gibt grep, aber dies ist ein Beispiel, und warum sollten wir zwei Dienstprogramme verwenden, wenn Sie nur eines verwenden können?), hätten wir dies getan:


dpkg -l | awk ' /'vim'/ {print $2} '

Dieser Befehl würde alle installierten Pakete ausgeben, die "vim" im Namen haben. Eine Sache an awk ist, dass es schnell ist. Wenn Sie "vim" durch "lib" ersetzen, ergibt das auf meinem System 1300 Pakete. Es wird Situationen geben, in denen die Daten, mit denen Sie arbeiten müssen, viel größer sind, und das ist ein Teil, in dem awk glänzt.

Wie auch immer, beginnen wir mit den Beispielen und werden im Folgenden einige Konzepte erklären. Aber vorher wäre es gut zu wissen, dass es mehrere awk-Dialekte und -Implementierungen gibt, und die hier vorgestellten Beispiele befassen sich mit GNU awk als Implementierung und Dialekt. Und aufgrund verschiedener Anführungszeichenprobleme gehen wir davon aus, dass Sie bash, ksh oder sh verwenden, wir unterstützen (t)csh nicht.

Beispiele für AWK-Befehle

Sehen Sie sich einige der folgenden Beispiele an, um ein Verständnis von awk zu erlangen und wie Sie es in Situationen auf Ihrem eigenen System anwenden können. Fühlen Sie sich frei, den Anweisungen zu folgen und einige dieser Befehle in Ihrem Terminal zu verwenden, um die Ausgabe zu sehen, die Sie zurückerhalten.

  1. Drucken Sie nur die Spalten eins und drei mit stdin.

    
    awk ' {print $1,$3} '
    
  2. Drucken Sie alle Spalten mit stdin.

    
    awk ' {print \$0} '
    
  3. Drucken Sie nur Elemente aus Spalte 2, die mit dem Muster mit stdin übereinstimmen.

    
    awk ' /'pattern'/ {print $2} '
    
  4. Genau wie make oder sed verwendet awk -f, um seine Anweisungen aus einer Datei zu erhalten, was nützlich ist, wenn es viel zu tun gibt und die Verwendung des Terminals unpraktisch wäre.

    
    awk -f script.awk inputfile
    
  5. Führen Sie das Programm mit den Daten aus der Eingabedatei aus.

    
    awk ' program ' inputfile
    
  6. Klassisches "Hallo, Welt" in awk.

    
    awk "BEGIN { print \"Hello, world!!\" }"
    
  7. Gibt aus, was in der Befehlszeile eingegeben wurde, bis EOF (^D).

    
    awk '{ print }'
    
  8. awk-Skript für das klassische "Hallo, Welt!" (machen Sie es mit chmod ausführbar und führen Sie es so aus, wie es ist).

    
    #! /bin/awk -f
    BEGIN { print "Hello, world!" }
    
  9. Kommentare in awk-Skripten.

    
    This is a program that prints \
    "Hello, world!"
    and exits
    
  10. Definieren Sie FS (Feldtrennzeichen) als null, im Gegensatz zu Leerzeichen, dem Standardwert.

    
    awk -F "" 'program' files
    
  11. FS kann auch ein regulärer Ausdruck sein.

    
    awk -F "regex" 'program' files
    
  12. Wird <'> drucken. Hier ist der Grund, warum wir Bourne-Kessel bevorzugen. 🙂



    
    awk 'BEGIN { print "Here is a single \
    quote <'\''>" }'
    
  13. Drucken Sie die Länge der längsten Linie.

    
    awk '{ if (length(\$0) > max) max = \
    length(\$0) }
    END { print max }' inputfile
    
  14. Drucken Sie alle Zeilen, die länger als 80 Zeichen sind.

    
    awk 'length(\$0) > 80' inputfile
    
  15. Gibt jede Zeile aus, die mindestens ein Feld enthält (NF steht für Number of Fields).

    
    awk 'NF > 0' data
    
  16. Drucken Sie sieben Zufallszahlen von 0 bis 100.

    
    awk 'BEGIN { for (i = 1; i <= 7; i++)
    print int(101 * rand()) }'
    
  17. Gibt die Gesamtzahl der Bytes aus, die von Dateien im aktuellen Verzeichnis verwendet werden.

    
    ls -l . | awk '{ x += $5 } ; END \
    { print "total bytes: " x }'
    total bytes: 7449362
    
  18. Gibt die Gesamtzahl der Kilobyte aus, die von Dateien im aktuellen Verzeichnis verwendet werden.

    
    ls -l . | awk '{ x += $5 } ; END \
    { print "total kilobytes: " (x + \
    1023)/1024 }'
    total kilobytes: 7275.85
    
  19. Drucken Sie eine sortierte Liste der Anmeldenamen.

    
    awk -F: '{ print $1 }' /etc/passwd | sort
    
  20. Gibt die Anzahl der Zeilen in einer Datei aus, da NR für Anzahl der Zeilen steht.

    
    awk 'END { print NR }' inputfile
    
  21. Drucken Sie die geraden Zeilen in einer Datei. Wie würden Sie die ungeraden Zeilen drucken?

    
    awk 'NR % 2 == 0' data
    
  22. Gibt die Gesamtzahl der Bytes der Dateien aus, die zuletzt im November geändert wurden.

    
    ls -l | awk '$6 == "Nov" { sum += $5 }
    END { print sum }'
    
  23. Regulärer Ausdruck, der allen Einträgen im ersten Feld entspricht, die mit einem großen j beginnen.

    
    awk '$1  /J/' inputfile
    
  24. Regulärer Ausdruck, der allen Einträgen im ersten Feld entspricht, die nicht mit einem großen j beginnen.

    
    awk '$1  !/J/' inputfile
    
  25. Vermeiden von doppelten Anführungszeichen in awk.

    
    awk 'BEGIN { print "He said \"hi!\" \
    to her." }'
    
  26. Druckt "<A>bcd"

    
    echo aaaabcd | awk '{ sub(/a+/, \
    "<A>"); print }'
    
  27. Beispiel für die Namensnennung; Versuch es 🙂

    
    ls -lh | awk '{ owner = $3 ; $3 = $3 \
    " 0wnz"; print $3 }' | uniq
    
  28. Ändern Sie den Bestand und drucken Sie ihn, mit dem Unterschied, dass der Wert des zweiten Feldes um 10 verringert wird.

    
    awk '{ $2 = $2 - 10; print \$0 }' inventory
    
  29. Auch wenn Feld sechs nicht im Bestand vorhanden ist, können Sie es erstellen, ihm Werte zuweisen und dann anzeigen.

    
    awk '{ $6 = ($5 + $4 + $3 + $2); print \
    $6' inventory
    
  30. OFS ist das Trennzeichen für das Ausgabefeld und der Befehl gibt "a::c:d" und "4" aus, da Feld zwei zwar ungültig ist, aber immer noch vorhanden ist, sodass es gezählt wird.

    
    echo a b c d | awk '{ OFS = ":"; $2 = ""
    > print \$0; print NF }'
    
  31. Ein weiteres Beispiel für die Erstellung von Feldern; Wie Sie sehen können, wird das Feld zwischen $4 (vorhanden) und $6 (zu erstellen) ebenfalls erstellt (als $5 mit einem leeren Wert), sodass die Ausgabe "a::c:d::new" "6" ist.

    
    echo a b c d | awk ’{ OFS = ":"; \
    $2 = ""; $6 = "new"
    > print \$0; print NF }’
    
  32. Verwerfen von drei Feldern (letzten), indem die Anzahl der Felder geändert wird.

    
    echo a b c d e f | awk ’\
    { print "NF =", NF;
    > NF = 3; print \$0 }’
    
  33. Dies ist ein regulärer Ausdruck, der das Feldtrennzeichen auf Leerzeichen und nichts anderes setzt (nicht gieriger Musterabgleich).

    
    FS=[ ]
    
  34. Dadurch wird nur "a" gedruckt.

    
    echo ' a b c d ' |  awk 'BEGIN { FS = \
    "[ \t\n]+" }
    > { print $2 }'
    
  35. Gibt nur die erste Übereinstimmung von RE (regulärer Ausdruck) aus.

    
    awk -n '/RE/{p;q;}' file.txt
    
  36. Setzt FS auf \\

    
    awk -F\\ '...' inputfiles ...
    
  37. Wenn wir einen Datensatz haben wie:
    John Doe
    1234 Unknown Ave.
    Doeville, MA
    Dieses Skript setzt das Feldtrennzeichen auf Zeilenumbruch, damit es problemlos auf Zeilen angewendet werden kann.

    
    BEGIN { RS = "" ; FS = "\n" }
    {
    print "Name is:", $1
    print "Address is:", $2
    print "City and State are:", $3
    print ""
    }
    
  38. Bei einer Datei mit zwei Feldern werden die Datensätze wie folgt gedruckt:
    "field1:field2

    Feld3; Feld4

    …; ..."
    Da ORS, das Trennzeichen für Ausgabedatensätze, auf zwei Zeilenumbrüche gesetzt ist und OFS "; ”

    
    awk 'BEGIN { OFS = ";"; ORS = "\n\n" }
    > { print $1, $2 }' inputfile
    
  39. Dadurch werden 17 und 18 ausgegeben, da der Ausgabe-ForMaT so festgelegt ist, dass Gleitkommawerte auf den nächstgelegenen ganzzahligen Wert gerundet werden.

    
    awk 'BEGIN {
    > OFMT = "%.0f" # print numbers as \
    integers (rounds)
    > print 17.23, 17.54 }'
    
  40. Sie können printf hauptsächlich so verwenden, wie Sie es in C verwenden.

    
    awk 'BEGIN {
    > msg = "Dont Panic!"
    > printf "%s\n", msg
    >} '
    
  41. Gibt das erste Feld als 10-stellige Zeichenfolge im linksbeinen Blocksatz und $2 normal daneben aus.

    
    awk '{ printf "%-10s %s\n", $1, \
    $2 }' inputfile
    
  42. Die Dinge schöner machen.

    
    awk 'BEGIN { print "Name  Number"
                 print "----  ------" }
         { printf "%-10s %s\n", $1, \
    $2 }' inputfile
    
  43. Einfaches Beispiel für die Datenextraktion, bei dem das zweite Feld in eine Datei mit dem Namen "phone-list" geschrieben wird.

    
    awk '{ print $2 > "phone-list" }' \
    inputfile
    
  44. Schreiben Sie die in $1 enthaltenen Namen in eine Datei, sortieren Sie das Ergebnis und geben Sie es in eine andere Datei aus (Sie können auch mit >> anhängen, wie Sie es in einer Shell tun würden).

    
    awk '{ print $1 > "names.unsorted"
           command = "sort -r > names.sorted"
           print $1 | command }’ inputfile
    
  45. Wird 9, 11, 17 drucken.

    
    awk 'BEGIN { printf "%d, %d, %d\n", 011, 11, \
    0x11 }'
    
  46. Einfache Suche nach foo oder bar.

    
    if (/foo/ || /bar/)
       print "Found!"
    
  47. Einfache arithmetische Operationen (die meisten Operatoren ähneln C sehr).

    
    awk '{ sum = $2 + $3 + $4 ; avg = sum / 3
    > print $1, avg }' grades
    
  48. Einfacher, erweiterbarer Taschenrechner.

    
    awk '{ print "The square root of", \
    $1, "is", sqrt($1) }'
    2
    The square root of 2 is 1.41421
    7
    The square root of 7 is 2.64575
    
  49. Druckt jeden Datensatz zwischen Start und Stopp.

    
    awk '$1 == "start", $1 == "stop"' inputfile
    
  50. BEGIN- und END-Regeln werden genau einmal ausgeführt, vor und nach jeder Datensatzverarbeitung.

    
    awk '
    > BEGIN { print "Analysis of \"foo\"" }
    > /foo/ { ++n }
    > END { print "\"foo\" appears", n,\
     "times." }’ inputfile
    
  51. Suche mit der Shell.

    
    echo -n "Enter search pattern: "
    read pattern
    awk "/$pattern/ "'{ nmatches++ }
    END { print nmatches, "found" }' inputfile
    
  52. Einfache Bedingung. awk unterstützt wie C auch die ?:-Operatoren.

    
    if (x % 2 == 0)
    print "x is even"
    else
    print "x is odd"
    
  53. Druckt die ersten drei Felder jedes Datensatzes, eines pro Zeile.

    
    awk '{ i = 1
      while (i <= 3) {
        print $i
        i++
      }
    }’ inputfile
    
  54. Druckt die ersten drei Felder jedes Datensatzes, eines pro Zeile.

    
    awk '{ for (i = 1; i <= 3; i++)
      print \$i
    }'
    
  55. Wenn Sie das Beenden mit einem anderen Fehlercode als 0 beenden, bedeutet dies, dass etwas nicht ganz in Ordnung ist. Hier ist ein Beispiel.

    
    BEGIN {
    if (("date" | getline date_now) <= 0) {
      print "Can't get system date" > \
    "/dev/stderr"
      exit 1
    }
    print "current date is", date_now
    close("date")
    }
    
  56. Druckt awk Datei1 Datei2.

    
    awk 'BEGIN {
    > for (i = 0; i < ARGC; i++)
    > print ARGV[i]
    > }’ file1 file2
    
  57. Löschen von Elementen in einem Array.

    
    for (i in frequencies)
    delete frequencies[i]
    
  58. Überprüfen Sie, ob Array-Elemente vorhanden sind.

    
    foo[4] = ""
    if (4 in foo)
    print "This is printed, even though foo[4] \
    is empty"
    
  59. Eine awk-Variante von ctime() in C. So definieren Sie Ihre eigenen Funktionen in awk.

    
    function ctime(ts, format)
    {
      format = "%a %b %d %H:%M:%S %Z %Y"
      if (ts == 0)
      ts = systime()
      # use current time as default
      return strftime(format, ts)
    }
    
  60. Ein Cliff-Zufallszahlengenerator.

    
    BEGIN { _cliff_seed = 0.1 }
    function cliff_rand()
    {
      _cliff_seed = (100 * log(_cliff_seed)) % 1
      if (_cliff_seed < 0)
        _cliff_seed = - _cliff_seed
      return _cliff_seed
    }
    
  61. Anonymisieren Sie ein Apache-Protokoll (IPs werden zufällig ausgewählt).

    
    cat apache-anon-noadmin.log | \
    awk 'function ri(n) \
    {  return int(n*rand()); }  \
    BEGIN { srand(); }  { if (! \
    ($1 in randip)) {  \
    randip[$1] = sprintf("%d.%d.%d.%d", \
    ri(255), ri(255)\
    , ri(255), ri(255)); } \
    $1 = randip[$1]; print \$0  }'
    

Schlussfolgerung

Wie Sie sehen können, können Sie mit awk viel Textverarbeitung und andere raffinierte Dinge erledigen. Wir sind nicht auf fortgeschrittenere Themen eingegangen, wie z.B. die vordefinierten Funktionen von awk, aber wir haben Ihnen genug gezeigt (hoffentlich), um es als mächtiges Werkzeug in Erinnerung zu behalten.

Verwandte Artikel: