Utilisation de plusieurs délimiteurs dans awk


202

J'ai un fichier qui contient les lignes suivantes:

/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

Dans la sortie ci-dessus, je veux extraire 3 champs (numéro 2, 4 et le dernier *.example.com). J'obtiens la sortie suivante:

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

Comment extraire également le dernier champ avec le nom de domaine qui se trouve après '='? Comment utiliser multiple delimiterpour extraire le champ?


2
Pour répondre à ma question qui est la même mais différente, awkc'était avaler des champs quand ils étaient vides ce qui empêchait la numérotation des champs. J'ai changé -F " "pour -F "[ ]"et awkn'ai plus avalé les champs vides.
Adam

Réponses:


324

Le délimiteur peut être une expression régulière.

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

Produit:

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

42
Bien sûr, catprocessus n'est pas nécessaire: awk '...' file. En outre, il serait plus judicieux d'utiliser le séparateur de champ de sortie:awk -F'[/=]' -v OFS="\t" '{print $3, $5, $8}'
glenn jackman

17
Les délimiteurs awk peuvent être des expressions régulières ... cela a fait ma journée!
das.cyklone

4
@ das.cyklone: ​​awk peut également avoir plusieurs séparateurs, avec |: ex: awk -F 'this|that|[=/]' '......' (utile pour avoir des mots / chaînes séparant les choses) (notez que cela garde les espaces dans les champs entre 2 séparateurs. L'ajout également |[ \t]+peut être utile, mais peut rendre les choses délicat ... comme il y a souvent des espaces avant et après 'ceci', cela fera apparaître 2 champs vides supplémentaires entre les espaces et 'ceci')
Olivier Dulac

J'ai essayé ceci sur 2 distributions différentes et j'obtiens le même comportement: je veux obtenir le port de netstat -ntpl "netstat -ntpl | sed 's /: / /' | awk '{print $ 5}'" fonctionne mais pourrait faire sans tuyauterie doulbe Cela fonctionne mais je ne m'attendais pas aux données sur le champ 17: "netstat -ntpl | awk -F" |: "'{print $ 17}'"
louigi600

2
oui ... cela m'a donné ce que je voulais: awk -F "[:] +" '/ \ / postmaster * $ / {print $ 5}'
louigi600

44

Bonnes nouvelles! awkle séparateur de champ peut être une expression régulière. Il vous suffit d'utiliser -F"<separator1>|<separator2>|...":

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

Retour:

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

Ici:

  • -F"/|="définit le séparateur de champ de saisie sur /ou =. Ensuite, il définit le séparateur de champ de sortie sur un onglet.

  • -vOFS='\t'utilise l' -vindicateur pour définir une variable. OFSest la variable par défaut pour le séparateur de champ de sortie et elle est définie sur le caractère de tabulation. Le drapeau est nécessaire car il n'y a pas de fonction intégrée pour l'OFS comme -F.

  • {print $3, $5, $NF} imprime les 3ème, 5ème et derniers champs en fonction du séparateur de champ d'entrée.


Voir un autre exemple:

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

Ce fichier a deux séparateurs de champs #et _. Si nous voulons imprimer le deuxième champ indépendamment du fait que le séparateur soit l'un ou l'autre, faisons que les deux soient des séparateurs!

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

Où les fichiers sont numérotés comme suit:

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

1
Merci @BUFU pour votre modification. J'ai supprimé la référence OFS pour me concentrer uniquement sur la partie FS, mais il est également bon de l'avoir. À votre santé!
fedorqui 'SO arrêtez de nuire'

5

Si votre espace est cohérent, vous pouvez l'utiliser comme délimiteur, également au lieu d'insérer \tdirectement, vous pouvez définir le séparateur de sortie et il sera inclus automatiquement:

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

3

Pour un séparateur de champ d'un nombre quelconque 2par 5lettre ou aou #ou un espace, où le caractère de séparation doit être répétée au moins 2 fois et pas plus de 6 fois, par exemple:

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

Je suis sûr que des variations existent en utilisant () et des paramètres


3

Perl one-liner:

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

Ces options de ligne de commande sont utilisées:

  • -nboucle autour de chaque ligne du fichier d'entrée, place la ligne dans la $_variable, n'imprime pas automatiquement chaque ligne

  • -l supprime les nouvelles lignes avant le traitement et les ajoute à nouveau après

  • -amode autosplit - perl divisera automatiquement les lignes d'entrée dans le @Ftableau. Par défaut, la division sur un espace blanc

  • -Fmodificateur autosplit, dans cet exemple se divise sur /ou=

  • -e exécuter le code perl

Perl est étroitement lié à awk, cependant, le @Ftableau de fractionnement automatique commence à l'index $F[0]tandis que les champs awk commencent par $ 1.


2

Une autre consiste à utiliser l'option -F mais à lui transmettre l'expression régulière pour imprimer le texte entre les parenthèses gauche et droite ().

Le contenu du fichier:

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

La commande:

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

résultat:

smbw
smbt
smbn
smbs

Utiliser awk pour simplement imprimer le texte entre []:

Utilisez awk -F'[][]' mais awk -F'[[]]'ne fonctionnera pas.

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


Votre réponse est apparue dans la file d'attente de suppression, car 9 fois sur 10, les utilisateurs ayant une réputation liée à leur propre blog sont généralement du spam. Mais le vôtre est l'exception à la règle. Les 10 dernières années de contenu, il y a une mine d'or, j'espère que vous avez un plan pour l'immortaliser.
Eric Leschinski

0

Je vois de nombreuses réponses parfaites sur le tableau, mais j'aimerais toujours télécharger mon morceau de code aussi,

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


2
print $3 " " $5 " " $7peut être imprimé tout comme print $3, $5, $7. De plus, je ne vois pas l'avantage d'utiliser awk puis de canaliser pour sed. En général, awk peut suffire et d'autres répondent le montrent.
fedorqui 'SO arrête de nuire'
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.