GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Awk Einzeiler und Skripte, die Ihnen beim Sortieren von Textdateien helfen

Awk ist der allgegenwärtige Unix-Befehl zum Scannen und Verarbeiten von Text mit vorhersagbaren Mustern. Da sie aber Funktionen enthält, wird sie zu Recht auch als Programmiersprache bezeichnet.

Verwirrenderweise gibt es mehr als ein awk. (Oder, wenn Sie glauben, dass es nur einen geben kann, dann gibt es mehrere Klone.) Es gibt awk , das Originalprogramm von Aho, Weinberger und Kernighan, und dann gibt es noch nawk , mawk , und die GNU-Version gawk . Die GNU-Version von awk ist eine hochportable, kostenlose Softwareversion des Dienstprogramms mit mehreren einzigartigen Funktionen, daher handelt dieser Artikel von GNU awk.

Während sein offizieller Name gawk ist, wird er auf GNU+Linux-Systemen als awk bezeichnet und dient als Standardversion dieses Befehls. Auf anderen Systemen, die nicht mit GNU awk ausgeliefert werden, müssen Sie es installieren und es als gawk statt als awk bezeichnen. In diesem Artikel werden die Begriffe awk und gawk synonym verwendet.

Da es sowohl ein Befehl als auch eine Programmiersprache ist, ist awk ein mächtiges Werkzeug für Aufgaben, die sonst vielleicht sortiert werden müssten , Schnitt , einzigartig , und andere gängige Dienstprogramme. Glücklicherweise gibt es in Open Source viel Platz für Redundanzen. Wenn Sie also mit der Frage konfrontiert werden, ob Sie awk verwenden sollen oder nicht, ist die Antwort wahrscheinlich ein solides „vielleicht.“

Das Schöne an der Flexibilität von awk ist, dass Sie, wenn Sie sich bereits dazu verpflichtet haben, awk für eine Aufgabe zu verwenden, wahrscheinlich in awk bleiben können, egal was auf dem Weg passiert. Dazu gehört auch die ewige Notwendigkeit, Daten anders zu sortieren als in der Reihenfolge, in der sie an Sie geliefert wurden.

Musterset

Bevor Sie die Sortiermethoden von awk erkunden, generieren Sie einen zu verwendenden Beispieldatensatz. Halten Sie es einfach, damit Sie nicht durch Grenzfälle und unbeabsichtigte Komplexität abgelenkt werden. Dies ist der Beispielsatz, den dieser Artikel verwendet:

Aptenodytes;forsteri;Miller,JF;1778;Emperor
Pygoscelis;papua;Wagler;1832;Gentoo
Eudyptula;minor;Bonaparte;1867;Little Blue
Spheniscus;demersus;Brisson;1760;African
Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
Torvaldis;linux;Ewing,L;1996;Tux

Es ist ein kleiner Datensatz, aber er bietet eine gute Auswahl an Datentypen:

  • Ein Gattungs- und Artname, die miteinander verbunden sind, aber als getrennt betrachtet werden
  • Ein Nachname, manchmal mit Anfangsbuchstaben nach einem Komma
  • Eine ganze Zahl, die ein Datum darstellt
  • Ein beliebiger Begriff
  • Alle Felder durch Semikolon getrennt

Abhängig von Ihrem Bildungshintergrund können Sie dies als ein 2D-Array oder eine Tabelle oder nur als eine durch Zeilen getrennte Sammlung von Daten betrachten. Wie Sie darüber denken, bleibt Ihnen überlassen, denn awk erwartet nicht mehr als Text. Es liegt an Ihnen, awk mitzuteilen, wie Sie es parsen möchten.

Der Sortier-Cheat

Wenn Sie einen Textdatensatz nur nach einem bestimmten, definierbaren Feld (denken Sie an eine "Zelle" in einer Tabellenkalkulation) sortieren möchten, können Sie den Sortierbefehl verwenden.

Felder und Datensätze

Unabhängig vom Format Ihrer Eingabe müssen Sie Muster darin finden, damit Sie sich auf die Teile der Daten konzentrieren können, die für Sie wichtig sind. In diesem Beispiel werden die Daten durch zwei Faktoren begrenzt:Zeilen und Felder. Jede neue Zeile repräsentiert einen neuen Datensatz , wie Sie es wahrscheinlich in einer Tabellenkalkulation oder einem Datenbank-Dump sehen würden. Innerhalb jeder Zeile gibt es verschiedene Felder (Stellen Sie sich diese als Zellen in einer Tabellenkalkulation vor), die durch Semikolons (;) getrennt sind.

Awk verarbeitet jeweils einen Datensatz, sodass Sie sich beim Strukturieren der Anweisungen, die Sie awk geben, auf nur eine Zeile konzentrieren können. Legen Sie fest, was Sie mit einer Zeile tun möchten, und testen Sie es dann (entweder im Kopf oder mit awk) in der nächsten Zeile und einigen weiteren. Am Ende haben Sie eine gute Hypothese darüber, was Ihr awk-Skript tun muss, um Ihnen die gewünschte Datenstruktur bereitzustellen.

In diesem Fall ist leicht zu erkennen, dass jedes Feld durch ein Semikolon getrennt ist. Nehmen Sie der Einfachheit halber an, Sie möchten die Liste nach dem allerersten Feld jeder Zeile sortieren.

Bevor Sie sortieren können, müssen Sie in der Lage sein, sich nur auf das erste Feld jeder Zeile zu konzentrieren, das ist also der erste Schritt. Die Syntax eines awk-Befehls in einem Terminal ist awk , gefolgt von relevanten Optionen, gefolgt von Ihrem awk-Befehl, und endet mit der Datei mit den Daten, die Sie verarbeiten möchten.

$ awk --field-separator=";" '{print $1;}' penguins.list
Aptenodytes
Pygoscelis
Eudyptula
Spheniscus
Megadyptes
Eudyptes
Torvaldis

Da das Feldtrennzeichen ein Zeichen ist, das für die Bash-Shell eine besondere Bedeutung hat, müssen Sie das Semikolon in Anführungszeichen setzen oder ihm einen umgekehrten Schrägstrich voranstellen. Dieser Befehl ist nur nützlich, um zu beweisen, dass Sie sich auf ein bestimmtes Feld konzentrieren können. Sie können denselben Befehl mit der Nummer eines anderen Felds versuchen, um den Inhalt einer anderen "Spalte" Ihrer Daten anzuzeigen:

$ awk --field-separator=";" '{print $3;}' penguins.list
Miller,JF
Wagler
Bonaparte
Brisson
Milne-Edwards
Viellot
Ewing,L

Noch ist nichts geklärt, aber das ist eine gute Vorarbeit.

Skripterstellung

Awk ist mehr als nur ein Befehl; Es ist eine Programmiersprache mit Indizes und Arrays und Funktionen. Das ist wichtig, denn es bedeutet, dass Sie eine Liste von Feldern abrufen können, nach denen Sie sortieren möchten, die Liste im Speicher speichern, verarbeiten und dann die resultierenden Daten drucken können. Für eine komplexe Reihe von Aktionen wie dieser ist es einfacher, in einer Textdatei zu arbeiten, also erstellen Sie eine neue Datei namens sorter.awk und geben Sie diesen Text ein:

#!/usr/bin/awk -f 

BEGIN {
        FS=";";
}

Dadurch wird die Datei als awk-Skript eingerichtet, das die in der Datei enthaltenen Zeilen ausführt.

Der BEGINN statement ist eine spezielle Setup-Funktion, die von awk für Aufgaben bereitgestellt wird, die nur einmal ausgeführt werden müssen. Definieren der eingebauten Variable FS , was für Feldtrenner steht und ist derselbe Wert, den Sie in Ihrem awk-Befehl mit --field-separator festgelegt haben , muss nur einmal vorkommen, also ist es in BEGIN enthalten Aussage.

Arrays in awk

Sie wissen bereits, wie Sie die Werte eines bestimmten Felds mithilfe von $ erfassen Notation zusammen mit der Feldnummer, aber in diesem Fall müssen Sie sie in einem Array speichern, anstatt sie auf dem Terminal auszugeben. Dies geschieht mit einem awk-Array. Das Wichtige an einem awk-Array ist, dass es Schlüssel und Werte enthält. Stellen Sie sich ein Array zu diesem Artikel vor; es würde etwa so aussehen:author:"seth",title:"How to sort with awk",length:1200 . Elemente wie Autor und Titel und Länge sind Schlüssel, wobei die folgenden Inhalte Werte sind.

Dies hat im Zusammenhang mit der Sortierung den Vorteil, dass Sie ein beliebiges Feld als Schlüssel und einen beliebigen Datensatz als Wert zuweisen und dann die eingebaute awk-Funktion asorti() verwenden können (nach Index sortieren), um nach dem Schlüssel zu sortieren. Gehen Sie jetzt willkürlich davon aus, dass Sie nur nach dem zweiten Feld sortieren möchten.

Awk-Aussagen nicht denen die speziellen Schlüsselwörter BEGIN vorangestellt sind oder ENDE sind Schleifen, die bei jedem Datensatz passieren. Dies ist der Teil des Skripts, der die Daten nach Mustern durchsucht und entsprechend verarbeitet. Jedes Mal, wenn awk seine Aufmerksamkeit auf einen Datensatz richtet, werden Anweisungen in {} (sofern nicht BEGIN vorangestellt ist oder ENDE ) ausgeführt werden.

Um einem Array einen Schlüssel und einen Wert hinzuzufügen, erstellen Sie eine Variable (in diesem Beispielskript nenne ich sie ARRAY , was nicht besonders originell, aber sehr übersichtlich ist), das ein Array enthält, und ihm dann einen Schlüssel in Klammern und einen Wert mit einem Gleichheitszeichen (=) zuweisen ).

{   # dump each field into an array
    ARRAY[$2] = $R;
}

In dieser Anweisung wird der Inhalt des zweiten Felds ($2 ) als Schlüsselbegriff und der aktuelle Datensatz ($R ) wird als Wert verwendet.

Die asorti()-Funktion

Zusätzlich zu Arrays verfügt awk über mehrere grundlegende Funktionen, die Sie als schnelle und einfache Lösungen für häufige Aufgaben verwenden können. Eine der in GNU awk eingeführten Funktionen, asorti() , bietet die Möglichkeit, ein Array nach Schlüssel (oder Index ) oder Wert.

Sie können das Array erst sortieren, wenn es gefüllt ist, was bedeutet, dass diese Aktion nicht bei jedem neuen Datensatz erfolgen muss, sondern nur in der letzten Phase Ihres Skripts. Dafür stellt awk das spezielle END zur Verfügung Stichwort. Die Umkehrung von BEGIN , ein ENDE Anweisung erfolgt nur einmal und erst nachdem alle Datensätze gescannt wurden.

Fügen Sie dies Ihrem Skript hinzu:

END {
    asorti(ARRAY,SARRAY);
    # get length
    j = length(SARRAY);
   
    for (i = 1; i <= j; i++) {
        printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
    }
}

Die asorti() Funktion übernimmt den Inhalt von ARRAY , sortiert sie nach Index und platziert die Ergebnisse in einem neuen Array namens SARRAY (ein willkürlicher Name, den ich für diesen Artikel erfunden habe und der Sortiertes ARRAY bedeutet ).

Als nächstes die Variable j (ein anderer willkürlicher Name) wird den Ergebnissen der Länge() zugewiesen Funktion, die die Anzahl der Elemente in SARRAY zählt .

Verwenden Sie schließlich ein for Schleife, um jedes Element in SARRAY zu durchlaufen mit printf() Funktion, um jeden Schlüssel zu drucken, gefolgt vom entsprechenden Wert dieses Schlüssels in ARRAY .

Das Skript ausführen

Um Ihr awk-Skript auszuführen, machen Sie es ausführbar:

$ chmod +x sorter.awk

Und dann gegen die penguin.list laufen lassen Beispieldaten:

$ ./sorter.awk penguins.list 
antipodes Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
chrysocome Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
demersus Spheniscus;demersus;Brisson;1760;African
forsteri Aptenodytes;forsteri;Miller,JF;1778;Emperor
linux Torvaldis;linux;Ewing,L;1996;Tux
minor Eudyptula;minor;Bonaparte;1867;Little Blue
papua Pygoscelis;papua;Wagler;1832;Gentoo

Wie Sie sehen können, werden die Daten nach dem zweiten Feld sortiert.

Dies ist ein wenig restriktiv. Es wäre besser, wenn Sie zur Laufzeit flexibel auswählen könnten, welches Feld Sie als Sortierschlüssel verwenden möchten, damit Sie dieses Skript für jeden Datensatz verwenden und aussagekräftige Ergebnisse erhalten können.

Befehlsoptionen hinzufügen

Sie können einem awk-Skript eine Befehlsvariable hinzufügen, indem Sie den Literalwert var verwenden in deinem Skript. Ändern Sie Ihr Skript so, dass Ihre iterative Klausel var verwendet beim Erstellen Ihres Arrays:

{ # dump each field into an array
    ARRAY[$var] = $R;
}

Versuchen Sie, das Skript so auszuführen, dass es nach dem dritten Feld sortiert, indem Sie -v var verwenden Option, wenn Sie es ausführen:

$ ./sorter.awk -v var=3 penguins.list 
Bonaparte Eudyptula;minor;Bonaparte;1867;Little Blue
Brisson Spheniscus;demersus;Brisson;1760;African
Ewing,L Torvaldis;linux;Ewing,L;1996;Tux
Miller,JF Aptenodytes;forsteri;Miller,JF;1778;Emperor
Milne-Edwards Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
Viellot Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
Wagler Pygoscelis;papua;Wagler;1832;Gentoo

Korrekturen

Dieser Artikel hat gezeigt, wie man Daten in reinem GNU awk sortiert. Das Skript kann verbessert werden, also verbringen Sie, wenn es für Sie nützlich ist, einige Zeit damit, awk-Funktionen auf der Manpage von gawk zu recherchieren und das Skript für eine bessere Ausgabe anzupassen.

Hier ist das bisher vollständige Skript:

#!/usr/bin/awk -f
# GPLv3 appears here
# usage: ./sorter.awk -v var=NUM FILE

BEGIN { FS=";"; }

{ # dump each field into an array
    ARRAY[$var] = $R;
}

END {
    asorti(ARRAY,SARRAY);
    # get length
    j = length(SARRAY);
   
    for (i = 1; i <= j; i++) {
        printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
    }
}

Linux
  1. So verwenden Sie Awk und reguläre Ausdrücke zum Filtern von Text oder Zeichenfolgen in Dateien

  2. So verwenden Sie den Grep-Befehl, um Text in Dateien zu finden

  3. 10 grundlegende Linux-Befehle, die Sie kennen müssen

  4. So sortieren Sie Dateien in Linux mit dem Sortierbefehl

  5. Befehl zum Auflisten aller Dateien außer . (Punkt) und .. (Punkt Punkt)

Wie man Textdateien unter Linux vergleicht und zusammenführt (Teil 2)

So verwenden Sie den cp-Befehl zum Kopieren von Dateien und Verzeichnissen

So sortieren Sie Dateien in Linux (GUI und Shell)

4 Möglichkeiten zum Übertragen von Dateien und Verzeichnissen unter Linux

40 Praktischer und nützlicher awk-Befehl in Linux und BSD

So finden und ersetzen Sie Text in Vim