GNU/Linux >> Tutoriels Linux >  >> Linux

Awk one-liners et scripts pour vous aider à trier les fichiers texte

Awk est la commande Unix omniprésente pour analyser et traiter du texte contenant des modèles prévisibles. Cependant, parce qu'il comporte des fonctions, on l'appelle aussi à juste titre un langage de programmation.

Confusément, il y a plus d'un awk. (Ou, si vous pensez qu'il ne peut y en avoir qu'un, alors il y a plusieurs clones.) Il y a awk , le programme original écrit par Aho, Weinberger et Kernighan, et puis il y a nawk , gueule , et la version GNU, gawk . La version GNU d'awk est une version hautement portable et gratuite de l'utilitaire avec plusieurs fonctionnalités uniques, donc cet article concerne GNU awk.

Alors que son nom officiel est gawk, sur les systèmes GNU+Linux, il est aliasé awk et sert de version par défaut de cette commande. Sur d'autres systèmes qui ne sont pas livrés avec GNU awk, vous devez l'installer et l'appeler gawk plutôt que awk. Cet article utilise indifféremment les termes awk et gawk.

Être à la fois un langage de commande et de programmation fait d'awk un outil puissant pour les tâches qui pourraient autrement être laissées à tri , couper , unique , et d'autres utilitaires courants. Heureusement, il y a beaucoup de place dans l'open source pour la redondance, donc si vous êtes confronté à la question d'utiliser ou non awk, la réponse est probablement un "peut-être" solide.

La beauté de la flexibilité d'awk est que si vous vous êtes déjà engagé à utiliser awk pour une tâche, vous pouvez probablement rester en awk, peu importe ce qui se passe en cours de route. Cela inclut le besoin éternel de trier les données d'une manière autre que l'ordre dans lequel elles vous ont été livrées.

Ensemble d'échantillons

Avant d'explorer les méthodes de tri d'awk, générez un exemple d'ensemble de données à utiliser. Restez simple afin de ne pas vous laisser distraire par des cas extrêmes et une complexité involontaire. Voici le jeu d'échantillons utilisé par cet article :

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

C'est un petit ensemble de données, mais il offre une bonne variété de types de données :

  • Un nom de genre et d'espèce, qui sont associés l'un à l'autre mais considérés comme distincts
  • Un nom de famille, parfois avec les premières initiales après une virgule
  • Un entier représentant une date
  • Un terme arbitraire
  • Tous les champs séparés par des points-virgules

En fonction de votre formation, vous pouvez considérer qu'il s'agit d'un tableau 2D ou d'un tableau ou simplement d'une collection de données délimitée par des lignes. La façon dont vous y pensez dépend de vous, car awk n'attend rien de plus que du texte. C'est à vous de dire à awk comment vous voulez l'analyser.

La triche de tri

Si vous souhaitez simplement trier un jeu de données texte en fonction d'un champ spécifique et définissable (pensez à une "cellule" dans une feuille de calcul), vous pouvez utiliser la commande de tri.

Champs et enregistrements

Quel que soit le format de votre entrée, vous devez y trouver des modèles afin de pouvoir vous concentrer sur les parties des données qui sont importantes pour vous. Dans cet exemple, les données sont délimitées par deux facteurs :des lignes et des champs. Chaque nouvelle ligne représente un nouvel enregistrement , comme vous le verriez probablement dans une feuille de calcul ou un vidage de base de données. Dans chaque ligne, il y a des champs distincts (considérez-les comme des cellules dans une feuille de calcul) séparées par des points-virgules (;).

Awk traite un enregistrement à la fois, donc pendant que vous structurez les instructions que vous donnerez à awk, vous pouvez vous concentrer sur une seule ligne. Établissez ce que vous voulez faire avec une ligne, puis testez-le (mentalement ou avec awk) sur la ligne suivante et quelques autres. Vous vous retrouverez avec une bonne hypothèse sur ce que votre script awk doit faire pour vous fournir la structure de données souhaitée.

Dans ce cas, il est facile de voir que chaque champ est séparé par un point-virgule. Par souci de simplicité, supposons que vous vouliez trier la liste par le tout premier champ de chaque ligne.

Avant de pouvoir trier, vous devez pouvoir vous concentrer uniquement sur le premier champ de chaque ligne, c'est donc la première étape. La syntaxe d'une commande awk dans un terminal est awk , suivi des options pertinentes, suivi de votre commande awk et se terminant par le fichier de données que vous souhaitez traiter.

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

Étant donné que le séparateur de champ est un caractère qui a une signification particulière pour le shell Bash, vous devez placer le point-virgule entre guillemets ou le faire précéder d'une barre oblique inverse. Cette commande n'est utile que pour prouver que vous pouvez vous concentrer sur un champ spécifique. Vous pouvez essayer la même commande en utilisant le numéro d'un autre champ pour afficher le contenu d'une autre "colonne" de vos données :

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

Rien n'a encore été trié, mais c'est une bonne base.

Scripts

Awk est plus qu'une simple commande; c'est un langage de programmation avec des indices, des tableaux et des fonctions. C'est important car cela signifie que vous pouvez saisir une liste de champs que vous souhaitez trier, stocker la liste en mémoire, la traiter, puis imprimer les données résultantes. Pour une série complexe d'actions comme celle-ci, il est plus facile de travailler dans un fichier texte, alors créez un nouveau fichier appelé sorter.awk et saisissez ce texte :

#!/usr/bin/awk -f 

BEGIN {
        FS=";";
}

Cela établit le fichier comme un script awk qui exécute les lignes contenues dans le fichier.

Le COMMENCER instruction est une fonction de configuration spéciale fournie par awk pour les tâches qui ne doivent se produire qu'une seule fois. Définition de la variable intégrée FS , qui signifie séparateur de champs et est la même valeur que vous avez définie dans votre commande awk avec --field-separator , ne doit se produire qu'une seule fois, il est donc inclus dans le BEGIN déclaration.

Tableaux dans awk

Vous savez déjà comment rassembler les valeurs d'un champ spécifique en utilisant le $ notation avec le numéro de champ, mais dans ce cas, vous devez le stocker dans un tableau plutôt que de l'imprimer sur le terminal. Cela se fait avec un tableau awk. La chose importante à propos d'un tableau awk est qu'il contient des clés et des valeurs. Imaginez un tableau à propos de cet article ; cela ressemblerait à ceci :author :"seth",title:"How to sort with awk",length:1200 . Des éléments comme auteur et titre et longueur sont des clés, les contenus suivants étant des valeurs.

L'avantage de cela dans le contexte du tri est que vous pouvez affecter n'importe quel champ comme clé et n'importe quel enregistrement comme valeur, puis utiliser la fonction awk intégrée asorti() (trier par index) pour trier par clé. Pour l'instant, supposez arbitrairement que vous seulement voulez trier par le deuxième champ.

Déclarations Awk pas précédé des mots clés spéciaux BEGIN ou FIN sont des boucles qui se produisent à chaque enregistrement. C'est la partie du script qui analyse les données à la recherche de modèles et les traite en conséquence. Chaque fois qu'awk tourne son attention vers un enregistrement, des déclarations en {} (sauf si précédé de BEGIN ou FIN ) sont exécutés.

Pour ajouter une clé et une valeur à un tableau, créez une variable (dans cet exemple de script, je l'appelle ARRAY , ce qui n'est pas très original, mais très clair) contenant un tableau, puis affectez-lui une clé entre parenthèses et une valeur avec un signe égal (= ).

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

Dans cette instruction, le contenu du deuxième champ ($2 ) sont utilisés comme terme clé, et l'enregistrement courant ($R ) est utilisé comme valeur.

La fonction asorti()

En plus des tableaux, awk possède plusieurs fonctions de base que vous pouvez utiliser comme solutions rapides et faciles pour les tâches courantes. Une des fonctions introduites dans GNU awk, asorti() , permet de trier un tableau par clé (ou index ) ou valeur.

Vous ne pouvez trier le tableau qu'une fois qu'il a été rempli, ce qui signifie que cette action ne doit pas se produire à chaque nouvel enregistrement, mais uniquement à la dernière étape de votre script. À cette fin, awk fournit le spécial END mot-clé. L'inverse de BEGIN , un FIN l'instruction n'a lieu qu'une seule fois et seulement après que tous les enregistrements ont été scannés.

Ajoutez ceci à votre script :

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

L'asorti() la fonction prend le contenu de ARRAY , le trie par index et place les résultats dans un nouveau tableau appelé SARRAY (un nom arbitraire que j'ai inventé pour cet article, signifiant Sorted ARRAY ).

Ensuite, la variable j (un autre nom arbitraire) reçoit les résultats de la length() fonction, qui compte le nombre d'éléments dans SARRAY .

Enfin, utilisez un pour boucle pour parcourir chaque élément dans SARRAY en utilisant printf() fonction pour imprimer chaque clé, suivie de la valeur correspondante de cette clé dans ARRAY .

Exécuter le script

Pour exécuter votre script awk, rendez-le exécutable :

$ chmod +x sorter.awk

Et puis exécutez-le contre le penguin.list exemple de données :

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

Comme vous pouvez le voir, les données sont triées par le deuxième champ.

C'est un peu restrictif. Il serait préférable d'avoir la possibilité de choisir au moment de l'exécution le champ que vous souhaitez utiliser comme clé de tri afin de pouvoir utiliser ce script sur n'importe quel ensemble de données et d'obtenir des résultats significatifs.

Ajout d'options de commande

Vous pouvez ajouter une variable de commande à un script awk en utilisant la valeur littérale var dans votre scénario. Modifiez votre script afin que votre clause itérative utilise var lors de la création de votre tableau :

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

Essayez d'exécuter le script afin qu'il trie par le troisième champ en utilisant la -v var option lorsque vous l'exécutez :

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

Corrections

Cet article a montré comment trier des données dans GNU awk pur. Le script peut être amélioré. Si cela vous est utile, passez du temps à rechercher les fonctions awk sur la page de manuel de gawk et personnalisez le script pour un meilleur résultat.

Voici le script complet jusqu'à présent :

#!/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. Comment utiliser Awk et des expressions régulières pour filtrer du texte ou une chaîne dans des fichiers

  2. Comment trouver le nombre de fichiers dans un répertoire et des sous-répertoires

  3. 10 commandes Linux de base que vous devez connaître

  4. Mode binaire et texte de la commande Md5sum ?

  5. Comment trier des fichiers sous Linux à l'aide de la commande Sort

Comment comparer et fusionner des fichiers texte sous Linux (partie 2)

Comment utiliser la commande cp pour copier des fichiers et des répertoires

Comment trier des fichiers sous Linux (GUI et Shell)

4 façons de transférer des fichiers et des répertoires sous Linux

40 Commande awk pratique et utile sous Linux et BSD

Comment rechercher et remplacer du texte dans Vim