Verwenden mehrerer Trennzeichen in awk


201

Ich habe eine Datei, die folgende Zeilen enthält:

/logs/tc0001/tomcat/tomcat7.1/conf/catalina.properties:app.env.server.name = demo.example.com
/logs/tc0001/tomcat/tomcat7.2/conf/catalina.properties:app.env.server.name = quest.example.com
/logs/tc0001/tomcat/tomcat7.5/conf/catalina.properties:app.env.server.name = www.example.com

In der obigen Ausgabe möchte ich 3 Felder extrahieren (Nummer 2, 4 und das letzte *.example.com). Ich erhalte die folgende Ausgabe:

cat file | awk -F'/' '{print $3 "\t" $5}'
tc0001   tomcat7.1
tc0001   tomcat7.2
tc0001   tomcat7.5

Wie extrahiere ich auch das letzte Feld mit dem nachfolgenden Domainnamen '='? Wie multiple delimiterextrahiere ich Felder?


2
Um meine Frage zu beantworten, die gleich, aber unterschiedlich ist, habe ich awkFelder verschluckt, als sie leer waren, was die Feldnummerierung beeinträchtigte. Ich wechselte -F " "zu -F "[ ]"und awkschluckte die leeren Felder nicht mehr.
Adam

Antworten:


323

Das Trennzeichen kann ein regulärer Ausdruck sein.

awk -F'[/=]' '{print $3 "\t" $5 "\t" $8}' file

Produziert:

tc0001   tomcat7.1    demo.example.com  
tc0001   tomcat7.2    quest.example.com  
tc0001   tomcat7.5    www.example.com

42
Natürlich catist kein Prozess erforderlich : awk '...' file. Es wäre auch ordentlicher, das Ausgabefeld-Trennzeichen zu verwenden:awk -F'[/=]' -v OFS="\t" '{print $3, $5, $8}'
Glenn Jackman

17
Awk-Begrenzer können reguläre Ausdrücke sein ... das war mein Tag!
das.cyklone

4
@ das.cyklone: ​​awk kann auch mehrere Trennzeichen haben, mit |: ex: awk -F 'this|that|[=/]' '......' (nützlich, wenn Wörter / Zeichenfolgen Dinge trennen) (Beachten Sie, dass dadurch die Leerzeichen in den Feldern zwischen zwei Trennzeichen erhalten |[ \t]+bleiben knifflig ... da es oft Leerzeichen vor und nach 'dies' gibt, erscheinen 2 zusätzliche leere Felder zwischen den Leerzeichen und 'dies')
Olivier Dulac

Ich habe dies auf 2 verschiedenen Distributionen versucht und ich bekomme das gleiche Verhalten: Ich möchte den Port von netstat -ntpl bekommen "netstat -ntpl | sed 's /: / /' | awk '{print $ 5}'" funktioniert aber könnte ohne Doulbe-Rohrleitungen auskommen Dies funktioniert, aber ich hatte die Daten in Feld 17 nicht erwartet: "netstat -ntpl | awk -F" |: "'{print $ 17}'"
louigi600

2
ja ... das hat mir das gebracht, was ich wollte: awk -F "[:] +" '/ \ / postmaster * $ / {print $ 5}'
louigi600

44

Gute Nachrichten! awkFeldtrennzeichen kann ein regulärer Ausdruck sein. Sie müssen nur verwenden -F"<separator1>|<separator2>|...":

awk -F"/|=" -vOFS='\t' '{print $3, $5, $NF}' file

Kehrt zurück:

tc0001  tomcat7.1  demo.example.com
tc0001  tomcat7.2  quest.example.com
tc0001  tomcat7.5  www.example.com

Hier:

  • -F"/|="Setzt das Eingabefeldtrennzeichen auf entweder /oder =. Anschließend wird das Ausgabefeldtrennzeichen auf eine Registerkarte gesetzt.

  • -vOFS='\t'verwendet das -vFlag zum Setzen einer Variablen. OFSist die Standardvariable für das Ausgabefeldtrennzeichen und wird auf das Tabulatorzeichen gesetzt. Das Flag ist notwendig, da es für das OFS kein eingebautes gibt -F.

  • {print $3, $5, $NF} druckt das 3., 5. und letzte Feld basierend auf dem Eingabefeldtrennzeichen.


Siehe ein anderes Beispiel:

$ cat file
hello#how_are_you
i#am_very#well_thank#you

Diese Datei hat zwei Feldtrennzeichen #und _. Wenn wir das zweite Feld drucken möchten, unabhängig davon, ob das Trennzeichen das eine oder das andere ist, lassen Sie uns beide Trennzeichen sein!

$ awk -F"#|_" '{print $2}' file
how
am

Wo die Dateien wie folgt nummeriert sind:

hello#how_are_you           i#am_very#well_thank#you
^^^^^ ^^^ ^^^ ^^^           ^ ^^ ^^^^ ^^^^ ^^^^^ ^^^
  1    2   3   4            1  2   3    4    5    6

1
Danke @BUFU für deine Bearbeitung. Ich habe die OFS-Referenz entfernt, um mich nur auf den FS-Teil zu konzentrieren, aber es ist auch gut, ihn zu haben. Prost!
fedorqui 'SO hör auf zu schaden'

5

Wenn Ihr Leerzeichen konsistent ist, können Sie dies als Trennzeichen verwenden. Anstatt es \tdirekt einzufügen , können Sie das Ausgabetrennzeichen festlegen und es wird automatisch eingefügt:

< file awk -v OFS='\t' -v FS='[/ ]' '{print $3, $5, $NF}'

3

Für ein Feldtrennzeichen einer beliebigen Zahl 2durch 5oder einen Buchstaben aoder #ein Leerzeichen, bei dem das Trennzeichen mindestens zweimal und höchstens sechsmal wiederholt werden muss, zum Beispiel:

awk -F'[2-5a# ]{2,6}' ...

Ich bin sicher, dass Variationen davon mit () und Parametern existieren


3

Perl Einzeiler:

perl -F'/[\/=]/' -lane 'print "$F[2]\t$F[4]\t$F[7]"' file

Diese Befehlszeilenoptionen werden verwendet:

  • -nSchleife um jede Zeile der Eingabedatei, füge die Zeile in die $_Variable ein, drucke nicht automatisch jede Zeile

  • -l Entfernt Zeilenumbrüche vor der Verarbeitung und fügt sie anschließend wieder hinzu

  • -aAutosplit-Modus - Perl teilt die Eingabezeilen automatisch in das @FArray auf. Standardmäßig wird auf Leerzeichen aufgeteilt

  • -FAutosplit-Modifikator, in diesem Beispiel entweder /oder=

  • -e Führen Sie den Perl-Code aus

Perl ist eng mit awk verwandt. Das @FAutosplit-Array beginnt jedoch am Index, $F[0]während awk-Felder mit $ 1 beginnen.


2

Eine andere Möglichkeit besteht darin, die Option -F zu verwenden, aber den regulären Ausdruck zu übergeben, um den Text zwischen der linken und / oder rechten Klammer zu drucken ().

Der Dateiinhalt:

528(smbw)
529(smbt)
530(smbn)
10115(smbs)

Der Befehl:

awk -F"[()]" '{print $2}' filename

Ergebnis:

smbw
smbt
smbn
smbs

Verwenden Sie awk, um den Text zwischen []folgenden Elementen zu drucken :

Verwenden Sie, awk -F'[][]' aber awk -F'[[]]'wird nicht funktionieren.

http://stanlo45.blogspot.com/2020/06/awk-multiple-field-separators.html


Ihre Antwort wurde in der Löschwarteschlange angezeigt, da 9 von 10 Benutzern mit 1 Ruf, die auf ihr eigenes Blog verlinken, normalerweise Spam sind. Aber deine ist die Ausnahme von der Regel. In den letzten 10 Jahren gab es eine Goldmine, hoffentlich haben Sie einen Plan, sie zu verewigen.
Eric Leschinski

0

Ich sehe viele perfekte Antworten an der Tafel, möchte aber trotzdem auch meinen Code hochladen.

awk -F"/" '{print $3 " " $5 " " $7}' sam | sed 's/ cat.* =//g'


2
print $3 " " $5 " " $7kann genauso gedruckt werden wie print $3, $5, $7. Außerdem sehe ich keinen Vorteil darin, awk zu verwenden und dann zu sed zu leiten. Im Allgemeinen kann awk ausreichen und andere Antworten zeigen dies.
Fedorqui 'SO hör auf zu schaden'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.