GNU/Linux >> Tutoriels Linux >  >> Linux

Séparateur de champ par défaut pour awk

Jetons un coup d'œil à la page de manuel GNU awk :

FS — Le séparateur de champ de saisie, un espace par défaut. Voir Champs , ci-dessus.

Vers les Champs rubrique !

Au fur et à mesure que chaque enregistrement d'entrée est lu, gawk divise l'enregistrement en champs, en utilisant la valeur de FS variable comme séparateur de champ. Si FS est un caractère unique, les champs sont séparés par ce caractère. Si FS est la chaîne nulle, chaque caractère individuel devient un champ distinct. Sinon, FS devrait être une expression régulière complète. Dans le cas particulier où FS est un espace unique, les champs sont séparés par des séries d'espaces et/ou de tabulations et/ou de nouvelles lignes.


Voici un résumé pragmatique qui s'applique à toutes les principales implémentations d'Awk :

  • GNU Awk (gawk ) - le awk par défaut dans quelques Distributions Linux
  • Mawk (mawk ) - le awk par défaut dans quelques Distributions Linux (par exemple, les versions antérieures d'Ubuntu)
  • BWK Awk - le awk par défaut sur les plates-formes de type BSD, y compris macOS

Versions récentes de tous ces implémentations suivent la norme POSIX en ce qui concerne le champ séparateurs (mais pas enregistrer séparateurs).

Glossaire :

  • RS est l'entrée-enregistrement séparateur , qui décrit comment l'entrée est divisée en enregistrements :

    • La valeur par défaut imposée par POSIX est une nouvelle ligne , également appelé \n dessous; c'est-à-dire que l'entrée est divisée en lignes par défaut .
    • Sur le awk la ligne de commande, RS peut être spécifié comme -v RS=<sep> .
    • POSIX limite RS à un littéral, un seul caractère valeur, mais GNU Awk et Mawk prennent en charge multi-caractère des valeurs qui peuvent être des expressions régulières étendues (BWK Awk ne fait pas soutenir cela).
  • FS est le champ d'entrée- séparateur , qui décrit comment chaque enregistrement est divisé en champs ; il peut s'agir d'une expression régulière étendue .

    • Sur le awk la ligne de commande, FS peut être spécifié comme -F <sep> (ou -v FS=<sep> ).
    • La valeur par défaut imposée par POSIX est formellement un espace (0x20 ), mais cet espace n'est pas littéralement interprété comme le (seul) séparateur, mais a une signification particulière ; voir ci-dessous.

Par défaut :

  • n'importe quelle course d'espaces et/ou onglets et/ou nouvelles lignes est traité comme un séparateur de champs
  • avec exécutions de début et de fin ignorées .

Notez que avec le séparateur d'enregistrement d'entrée par défaut (RS ), \n , nouvelles lignes généralement ne saisissez pas l'image comme séparateur de champs , car aucun enregistrement lui-même contient \n dans ce cas.

Les retours à la ligne comme séparateurs de champs le font entrer en jeu , cependant :

  • Quand RS est défini sur une valeur qui se traduit par des enregistrements eux-mêmes contenant \n cas (comme lorsque RS est défini sur la chaîne vide; voir ci-dessous).
  • Généralement , lorsque le split() La fonction est utilisée pour diviser une chaîne en éléments de tableau sans argument de séparateur de champ explicite.
    • Même si les enregistrements d'entrée ne contiendra pas \n instances dans le cas où la valeur par défaut RS est en vigueur, le split() fonction lorsqu'elle est invoquée sans argument de séparateur de champ explicite sur une chaîne multiligne provenant d'une source différente (par exemple, une variable passée via le -v option ou comme pseudo-nom de fichier) toujours traite \n comme séparateur de champs.

Considérations importantes NON par défaut :

  • Attribuer le vide chaîne à RS a une signification particulière  :il lit l'entrée en mode paragraphe , ce qui signifie que l'entrée est divisée en enregistrements par des séries de lignes non vides , avec les séries de lignes vides de début et de fin ignorées .

  • Lorsque vous attribuez quoi que ce soit d'autre qu'un littéral espace à FS , l'interprétation de FS change fondamentalement :

    • Un célibataire caractère ou chaque caractère d'un jeu de caractères spécifié est reconnu individuellement comme séparateur de champs - ne fonctionne de celui-ci, comme par défaut.
      • Par exemple, définir FS à [ ] - même si c'est efficacement équivaut à un seul espace - provoque chaque individu instance d'espace dans chaque enregistrement à traiter comme un séparateur de champ.
      • Pour reconnaître les courses , le quantificateur de regex (symbole de duplication) + doit être utilisé; par exemple, [\t]+ reconnaîtrait les courses d'onglets comme un seul séparateur.
    • Avant et arrière les séparateurs ne sont PAS ignorés , et, à la place, séparez empty champs.
    • Paramètre FS à la chaîne vide signifie que chaque caractère d'un enregistrement est son propre champ .
  • Comme mandaté par POSIX, si RS est défini sur la chaîne vide (mode paragraphe), nouvelles lignes (\n ) sont aussi considérés comme des séparateurs de champs , quelle que soit la valeur de FS .

  • Avec -P en vigueur et RS défini sur la chaîne vide , \n est toujours traité comme un séparateur de champs :
    gawk -P -F' ' -v RS='' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
  • Avec -P en vigueur et un non vide RS , \n n'est PAS traité comme un séparateur de champs - c'est le comportement obsolète :
    gawk -P -F' ' -v RS='|' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
    Un correctif arrive , selon les mainteneurs de GNU Awk ; attendez-vous à la version 4.2 (pas de délai indiqué).
    (Tip du chapeau à @JohnKugelman et @EdMorton pour leur aide.)

'[ ]+' fonctionne pour moi. Exécutez awk -W version pour obtenir la version awk. Le mien est 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

Par exemple, je veux obtenir le port d'écoute. J'ai donc besoin d'utiliser le délimiteur par défaut awk ajouté avec ':'

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

Si vous voulez juste tester le délimiteur par défaut, vous pouvez exécuter

# 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

Le résultat est comme prévu.


La question the default delimiter is only space for awk? est ambigu, mais je vais essayer de répondre aux deux questions que vous pourriez vous poser.

La valeur par défaut du FS variable (qui contient le séparateur de champ qui indique à awk comment séparer les enregistrements en champs lorsqu'il les lit) est un caractère d'espacement unique.

La chose qu'awk utilise pour séparer les enregistrements en champs est un "séparateur de champs" qui est une expression régulière avec des fonctionnalités supplémentaires qui ne s'appliquent que lorsque le séparateur de champs est un seul caractère vide. Cette fonctionnalité supplémentaire est la suivante :

  1. Les espaces blancs de début et de fin sont ignorés lors du fractionnement des champs.
  2. Les champs sont séparés par des chaînes d'espaces contigus comprenant des espaces, des tabulations et des retours à la ligne.
  3. Si vous souhaitez utiliser un caractère blanc littéral comme séparateur de champ, vous devez le spécifier sous la forme [ ] au lieu d'un caractère vide littéral autonome comme vous pourriez le faire dans une expression régulière.

En plus des séparateurs de champs utilisés pour diviser les enregistrements en champs lors de la lecture de l'entrée, ils sont utilisés dans d'autres contextes, par ex. le 3ème argument pour split() , il est donc important que vous sachiez quels contextes nécessitent une chaîne ou une expression régulière ou un champsep et la page de manuel spécifie clairement chacun.

Entre autres choses, ce qui précède explique ceci :

$ 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>

donc si vous ne comprenez pas pourquoi les 2 premiers produisent le même résultat mais que le dernier est différent, veuillez demander.


Linux
  1. Comment ajouter un chemin d'inclusion par défaut pour GCC sous Linux ?

  2. commande cut ou awk pour imprimer le premier champ de la première ligne

  3. Comment définir umask par défaut pour le servlet Webdav Tomcat ?

  4. Qu'est-ce qui constitue un 'champ' pour la commande cut ?

  5. Trier avec séparateur de champs

5 meilleurs lanceurs d'applications pour Ubuntu

Changer le shell par défaut pour Terminator ?

Tutoriel Regex pour les exemples Linux (Sed &AWK)

Quel est le mot de passe root par défaut pour MySQL 5.7

meilleur utilitaire d'exploration d'espace disque graphique pour Ubuntu ?

grep pour le terme et exclure un autre terme