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

Standard-Feldtrennzeichen für awk

Werfen wir einen Blick auf die Manpage von GNU awk:

FS — Das Eingabefeld-Trennzeichen, standardmäßig ein Leerzeichen. Siehe Felder , oben.

Zu den Feldern Abschnitt!

Während jeder Eingabedatensatz gelesen wird, teilt gawk den Datensatz unter Verwendung des Werts von FS in Felder auf Variable als Feldtrenner. Wenn FS ein einzelnes Zeichen ist, werden Felder durch dieses Zeichen getrennt. Wenn FS die Nullzeichenfolge ist, dann wird jedes einzelne Zeichen zu einem separaten Feld. Andernfalls FS wird als vollständiger regulärer Ausdruck erwartet. Im speziellen Fall, dass FS ein einzelnes Leerzeichen ist, Felder werden durch Reihen von Leerzeichen und/oder Tabulatoren und/oder Zeilenumbrüchen getrennt.


Hier ist eine pragmatische Zusammenfassung das gilt für alle wichtigen Awk-Implementierungen :

  • GNU Awk (gawk ) - der Standardwert awk in einigen Linux-Distributionen
  • Mawk (mawk ) - der Standardwert awk in einigen Linux-Distributionen (z. B. frühere Versionen von Ubuntu)
  • BWK Awk - der Standard awk auf BSD-ähnlichen Plattformen, einschließlich macOS

Aktuelle Versionen von all diese Implementierungen folgen dem POSIX-Standard in Bezug auf field Trennzeichen (aber nicht aufzeichnen Trennzeichen).

Glossar:

  • RS ist der Eingabe-Datensatz Trennzeichen , die beschreibt, wie die Eingabe in Datensätze aufgeteilt wird :

    • Der von POSIX vorgegebene Standardwert ist ein Zeilenumbruch , auch als \n bezeichnet unter; das heißt, die Eingabe wird in Zeilen aufgeteilt standardmäßig .
    • Am awk Befehlszeile von RS kann als -v RS=<sep> angegeben werden .
    • POSIX beschränkt RS zu einem Literal, Einzelzeichen Wert, aber GNU Awk und Mawk unterstützen mehrere Zeichen Werte, die erweiterte reguläre Ausdrücke sein können (BWK Awk tut nicht unterstütze das).
  • FS ist das Eingabe-Feld Trennzeichen , die beschreibt, wie jeder Datensatz ist in Felder aufgeteilt ; es kann sich um einen erweiterten regulären Ausdruck handeln .

    • Am awk Befehlszeile von FS kann als -F <sep> angegeben werden (oder -v FS=<sep> ).
    • Der von POSIX vorgeschriebene Standardwert ist formal ein Leerzeichen (0x20 ), aber dieses Leerzeichen ist nicht buchstäblich als (einziges) Trennzeichen interpretiert, hat aber besondere Bedeutung ; siehe unten.

Standardmäßig :

  • beliebiger Lauf von Leerzeichen und/oder Tabs und/oder Zeilenumbrüche wird als Feldtrennzeichen behandelt
  • wobei führende und nachlaufende Läufe ignoriert werden .

Beachten Sie das mit dem standardmäßigen Trennzeichen für Eingabedatensätze (RS ), \n , Zeilenumbrüche normalerweise Geben Sie das Bild nicht als Feldtrenner ein , weil kein Datensatz selbst enthält \n in diesem Fall.

Zeilenumbrüche als Feldtrenner tun ins Spiel kommen , jedoch:

  • Wenn RS auf einen Wert gesetzt, der zu Datensätzen selbst führt enthält \n Instanzen (z. B. wenn RS wird auf die leere Zeichenfolge gesetzt; siehe unten).
  • Allgemein , wenn der split() Die Funktion wird verwendet, um einen String ohne explizites Feldtrennargument in Array-Elemente aufzuteilen.
    • Obwohl die Eingabedatensätze enthält nicht \n Instanzen im Fall der Vorgabe RS In Kraft ist der split() Funktion, wenn sie ohne ein explizites Feldtrenner-Argument für eine mehrzeilige Zeichenfolge aus einer anderen Quelle aufgerufen wird (z. B. eine Variable, die über -v übergeben wird Option oder als Pseudo-Dateiname) immer behandelt \n als Feldtrenner.

Wichtige NICHT standardmäßige Überlegungen :

  • Zuweisen des leeren Zeichenfolge zu RS hat eine besondere Bedeutung :Es liest die Eingabe im Absatzmodus , was bedeutet, dass die Eingabe durch Läufe von nicht leeren Zeilen in Datensätze aufgeteilt wird , wobei führende und nachfolgende Leerzeilen ignoriert werden .

  • Wenn Sie etwas anderes zuweisen als ein Literal Leerzeichen zu FS , die Interpretation von FS ändert sich grundlegend :

    • Eine Single Zeichen oder jedes Zeichen aus einem bestimmten Zeichensatz wird individuell anerkannt als Feldtrenner - nicht läuft davon, wie bei der Voreinstellung.
      • Zum Beispiel das Setzen von FS bis [ ] - obwohl es effektiv entspricht einem einzigen Leerzeichen - bewirkt jedes individuelle Leerzeichen in jedem Datensatz, der als Feldtrennzeichen behandelt werden soll.
      • Um Läufe zu erkennen , der Regex-Quantifizierer (Duplizierungssymbol) + muss benutzt werden; B. [\t]+ würde Läufe erkennen von Tabulatoren als einzelnes Trennzeichen.
    • Führend und nachlaufend Trennzeichen werden NICHT ignoriert , und trennen Sie stattdessen leer Felder.
    • Einstellung FS zum leeren String bedeutet, dass jedes Zeichen eines Datensatzes ist sein eigenes Feld .
  • Wie von POSIX vorgeschrieben, wenn RS wird auf die leere Zeichenfolge gesetzt (Absatzmodus), Zeilenumbrüche (\n ) sind auch gelten als Feldtrenner , unabhängig vom Wert von FS .

  • Mit -P in Kraft und RS auf den leeren String setzen , \n ist noch als Feldtrenner behandelt:
    gawk -P -F' ' -v RS='' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
  • Mit -P in Kraft und ein nicht leerer RS , \n wird NICHT als Feldtrenner behandelt - das ist das obsolete Verhalten:
    gawk -P -F' ' -v RS='|' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
    Ein Fix kommt bald , laut den Betreuern von GNU Awk; erwarten Sie es in Version 4.2 (kein Zeitrahmen angegeben).
    (Dank an @JohnKugelman und @EdMorton für ihre Hilfe.)

'[ ]+' funktioniert bei mir. Führen Sie awk -W version aus um die awk-Version zu erhalten. Meine ist GNU Awk 4.0.2 .

# cat a.txt
tcp        0      0 10.192.25.199:65002     0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:26895         0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:18422           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 10.192.25.199:8888      0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:50010           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:50075           0.0.0.0:*               LISTEN
tcp        0      0 10.192.25.199:8093      0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:8670            0.0.0.0:*               LISTEN

Zum Beispiel möchte ich den Listen-Port erhalten. Also muss ich das awk-Standardtrennzeichen verwenden, das mit ':'

hinzugefügt wurde
# cat a.txt  | awk -F '[ ]+|:' '{print $5}'
65002
26895
111
18422
22
8888
50010
50075
8093
8670

Wenn Sie nur das Standardtrennzeichen testen möchten, können Sie

ausführen
# cat a.txt  | awk -F '[ ]+' '{print $4}'
10.192.25.199:65002
127.0.0.1:26895
0.0.0.0:111
0.0.0.0:18422
0.0.0.0:22
10.192.25.199:8888
0.0.0.0:50010
0.0.0.0:50075
10.192.25.199:8093
0.0.0.0:8670

Das Ergebnis ist wie erwartet.


Die Frage the default delimiter is only space for awk? ist mehrdeutig, aber ich werde versuchen, beide Fragen zu beantworten, die Sie vielleicht stellen.

Der Standardwert von FS Variable (die das Feldtrennzeichen enthält, das awk mitteilt, wie Datensätze beim Lesen in Felder getrennt werden sollen) ist ein einzelnes Leerzeichen.

Das, was awk verwendet, um Datensätze in Felder zu trennen, ist ein "Feldtrennzeichen", das ein regulärer Ausdruck mit einigen zusätzlichen Funktionen ist, die nur gelten, wenn das Feldtrennzeichen ein einzelnes Leerzeichen ist. Diese zusätzliche Funktionalität ist die:

  1. Führende und nachgestellte Leerzeichen werden bei der Feldaufteilung ignoriert.
  2. Felder werden durch Ketten von zusammenhängenden Leerzeichen getrennt, die Leerzeichen, Tabulatoren und Zeilenumbrüche enthalten.
  3. Wenn Sie ein wörtliches Leerzeichen als Feldtrennzeichen verwenden möchten, müssen Sie es als [ ] angeben Anstatt nur ein eigenständiges literales Leerzeichen, wie Sie es in einem regulären Ausdruck könnten.

Zusätzlich dazu, dass Feldtrennzeichen verwendet werden, um Datensätze beim Lesen der Eingabe in Felder aufzuteilen, werden sie in einigen anderen Kontexten verwendet, z. das 3. Argument für split() , daher ist es wichtig, dass Sie wissen, welche Kontexte einen String, einen regulären Ausdruck oder einen Fieldsep erfordern, und die Manpage gibt dies jeweils klar an.

Obiges erklärt unter anderem dies:

$ echo ' a b c ' | awk '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F' ' '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F'[ ]' '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'                              
5: <> <a> <b>

Wenn Sie also nicht verstehen, warum die ersten 2 dieselbe Ausgabe erzeugen, die letzte jedoch anders ist, fragen Sie bitte.


Linux
  1. So legen Sie Standardoptionen für die automatische Bereitstellung von Wechselmedien fest

  2. Ein gutes Standard-Backend für Matplotlib?

  3. In der Schleife gefangen? Awk While, Do While, For Loop, Break, Continue, Exit Beispiele

  4. 9 leistungsstarke integrierte Awk-Funktionen für Zahlen

  5. Wie füge ich einen standardmäßigen Include-Pfad für GCC in Linux hinzu?

Die 5 besten Anwendungsstarter für Ubuntu

Standard-Shell für Terminator ändern?

Regex-Tutorial für Linux-Beispiele (Sed &AWK).

bestes grafisches Festplatten-Explorer-Dienstprogramm für Ubuntu?

Was ist die Standarddatei für „hostname“?

Wie ändere ich das Von:Feld für E-Mails von Cron?