Recherche de site Web

Apprendre les commandes Linux : awk


Dans le cas de cet article, le titre Learning Linux Commands : awk peut être un peu trompeur. Et c’est parce que awk est plus qu’une commande, c’est un langage de programmation à part entière. Vous pouvez écrire des scripts awk pour des opérations complexes ou vous pouvez utiliser awk à partir de la ligne de commande. Le nom signifie Aho, Weinberger et Kernighan (oui, Brian Kernighan), les auteurs du langage, qui a été lancé en 1977, donc il partage le même esprit Unix que les autres utilitaires classiques *nix.

Si vous vous habituez à la programmation C ou si vous la connaissez déjà, vous verrez quelques concepts familiers dans awk, d’autant plus que le 'k' dans awk représente la même personne que le 'k' dans K&R, la bible de la programmation C. Vous aurez besoin de quelques connaissances en ligne de commande sous Linux et éventuellement de quelques bases de script, mais la dernière partie est facultative, car nous essaierons d’offrir quelque chose pour tout le monde. Un grand merci à Arnold Robbins pour tout son travail impliqué dans awk.

Dans ce tutoriel, vous allez apprendre :

  • Que fait awk ? Comment cela fonctionne-t-il ?
  • Concepts de base d’awk
  • Apprenez à utiliser awk à travers des exemples de ligne de commande

Apprentissage de la commande awk à travers divers exemples de ligne de commande sur Linux

Que fait awk ?

awk est un utilitaire/langage conçu pour l’extraction de données. Si le mot « extraction » vous dit quelque chose, c’est parce que awk était autrefois l’inspiration de Larry Wall lorsqu’il a créé Perl. awk est souvent utilisé avec sed pour effectuer des tâches de manipulation de texte utiles et pratiques, et cela dépend de la tâche si vous devez utiliser awk ou Perl, mais aussi de vos préférences personnelles. Tout comme sed, awk lit une ligne à la fois, effectue une action en fonction de la condition que vous lui donnez et affiche le résultat.

L’une des utilisations les plus simples et les plus populaires d’awk consiste à sélectionner une colonne à partir d’un fichier texte ou de la sortie d’une autre commande. Une chose que je faisais avec awk était, si j’installais Debian sur mon deuxième poste de travail, d’obtenir une liste des logiciels installés à partir de ma boîte principale, puis de la transmettre à aptitude. Pour cela, j’ai fait quelque chose comme ça :


dpkg -l | awk ' {print $2} ' > installed

La plupart des gestionnaires de paquets offrent aujourd’hui cette fonctionnalité, par exemple les options -qa de rpm, mais le résultat est supérieur à ce que je veux. Je vois que la deuxième colonne de la sortie de dpkg -l contient le nom des paquets installés, c’est pourquoi j’ai utilisé $2 avec awk : pour ne me donner que la 2ème colonne.

Concepts de base

Comme vous l’avez remarqué, l’action à effectuer par awk est entourée d’accolades, et toute la commande est citée. Mais la syntaxe est awk ' condition { action }'. Dans notre exemple, nous n’avions aucune condition, mais si nous voulions, par exemple, vérifier uniquement les paquets liés à vim installés (oui, il y a grep, mais c’est un exemple, et pourquoi utiliser deux utilitaires alors que vous ne pouvez en utiliser qu’un seul ?), nous aurions fait ceci :


dpkg -l | awk ' /'vim'/ {print $2} '

Cette commande afficherait tous les paquets installés dont le nom contient « vim ». Une chose à propos d’awk, c’est qu’il est rapide. Si vous remplacez « vim » par « lib », sur mon système, cela donne 1300 paquets. Il y aura des situations où les données avec lesquelles vous devrez travailler seront beaucoup plus volumineuses, et c’est l’une des parties où awk brille.

Quoi qu’il en soit, commençons par les exemples, et nous expliquerons quelques concepts au fur et à mesure. Mais avant cela, il serait bon de savoir qu’il existe plusieurs dialectes et implémentations d’awk, et les exemples présentés ici traitent de GNU awk, en tant qu’implémentation et dialecte. Et en raison de divers problèmes de guillemets, nous supposons que vous utilisez bash, ksh ou sh, nous ne supportons pas (t)csh.

Exemples de commandes awk

Consultez certains des exemples ci-dessous pour comprendre awk et comment vous pouvez l’appliquer dans des situations sur votre propre système. N’hésitez pas à suivre et à utiliser certaines de ces commandes dans votre terminal pour voir la sortie que vous obtenez.

  1. Imprimez uniquement les colonnes un et trois à l’aide de stdin.

    
    awk ' {print $1,$3} '
    
  2. Imprimez toutes les colonnes à l’aide de stdin.

    
    awk ' {print \$0} '
    
  3. Imprimez uniquement les éléments de la colonne 2 qui correspondent au motif à l’aide de stdin.

    
    awk ' /'pattern'/ {print $2} '
    
  4. Tout comme make ou sed, awk utilise -f pour obtenir ses instructions à partir d’un fichier, ce qui est utile lorsqu’il y a beaucoup à faire et que l’utilisation du terminal serait peu pratique.

    
    awk -f script.awk inputfile
    
  5. Exécuter le programme à l’aide des données du fichier d’entrée.

    
    awk ' program ' inputfile
    
  6. Classique « Hello, world » en awk.

    
    awk "BEGIN { print \"Hello, world!!\" }"
    
  7. Affiche ce qui est entré sur la ligne de commande jusqu’à EOF (^D).

    
    awk '{ print }'
    
  8. awk pour le classique « Hello, world ! » (rendez-le exécutable avec chmod et exécutez-le tel quel).

    
    #! /bin/awk -f
    BEGIN { print "Hello, world!" }
    
  9. Commentaires dans les scripts awk.

    
    This is a program that prints \
    "Hello, world!"
    and exits
    
  10. Définissez le FS (séparateur de champs) comme null, par opposition aux espaces, par défaut.

    
    awk -F "" 'program' files
    
  11. FS peut également être une expression régulière.

    
    awk -F "regex" 'program' files
    
  12. Imprimera <'>. Voici pourquoi nous préférons les coquilles Bourne. 🙂



    
    awk 'BEGIN { print "Here is a single \
    quote <'\''>" }'
    
  13. Imprimez la longueur de la ligne la plus longue.

    
    awk '{ if (length(\$0) > max) max = \
    length(\$0) }
    END { print max }' inputfile
    
  14. Imprimez toutes les lignes de plus de 80 caractères.

    
    awk 'length(\$0) > 80' inputfile
    
  15. Imprime chaque ligne comportant au moins un champ (NF signifie Number of Fields).

    
    awk 'NF > 0' data
    
  16. Imprimez sept nombres aléatoires de 0 à 100.

    
    awk 'BEGIN { for (i = 1; i <= 7; i++)
    print int(101 * rand()) }'
    
  17. Affiche le nombre total d’octets utilisés par les fichiers du répertoire courant.

    
    ls -l . | awk '{ x += $5 } ; END \
    { print "total bytes: " x }'
    total bytes: 7449362
    
  18. Affiche le nombre total de kilo-octets utilisés par les fichiers du répertoire courant.

    
    ls -l . | awk '{ x += $5 } ; END \
    { print "total kilobytes: " (x + \
    1023)/1024 }'
    total kilobytes: 7275.85
    
  19. Imprime la liste triée des noms de connexion.

    
    awk -F: '{ print $1 }' /etc/passwd | sort
    
  20. Imprime le nombre de lignes d’un fichier, car NR signifie Nombre de lignes.

    
    awk 'END { print NR }' inputfile
    
  21. Imprimez les lignes paires dans un fichier. Comment imprimeriez-vous les lignes impaires ?

    
    awk 'NR % 2 == 0' data
    
  22. Imprime le nombre total d’octets des fichiers qui ont été modifiés pour la dernière fois en novembre.

    
    ls -l | awk '$6 == "Nov" { sum += $5 }
    END { print sum }'
    
  23. Expression régulière correspondant à toutes les entrées du premier champ qui commencent par un j majuscule.

    
    awk '$1  /J/' inputfile
    
  24. Expression régulière correspondant à toutes les entrées du premier champ qui ne commencent pas par un j majuscule.

    
    awk '$1  !/J/' inputfile
    
  25. Échapper aux guillemets doubles dans awk.

    
    awk 'BEGIN { print "He said \"hi!\" \
    to her." }'
    
  26. Estampes « <A>bcd »

    
    echo aaaabcd | awk '{ sub(/a+/, \
    "<A>"); print }'
    
  27. Exemple d’attribution ; Essaie 🙂

    
    ls -lh | awk '{ owner = $3 ; $3 = $3 \
    " 0wnz"; print $3 }' | uniq
    
  28. Modifiez l’inventaire et imprimez-le, à la différence que la valeur du deuxième champ sera diminuée de 10.

    
    awk '{ $2 = $2 - 10; print \$0 }' inventory
    
  29. Même si la zone six n’existe pas dans l’inventaire, vous pouvez la créer et lui attribuer des valeurs, puis l’afficher.

    
    awk '{ $6 = ($5 + $4 + $3 + $2); print \
    $6' inventory
    
  30. OFS est le séparateur de champ de sortie et la commande affichera « a ::c :d » et « 4 » car bien que le champ deux soit annulé, il existe toujours donc il est compté.

    
    echo a b c d | awk '{ OFS = ":"; $2 = ""
    > print \$0; print NF }'
    
  31. Un autre exemple de création de champs ; Comme vous pouvez le voir, le champ entre $4 (existant) et $6 (à créer) est également créé (comme $5 avec une valeur vide), donc le résultat sera « a ::c :d ::new » « 6 ».

    
    echo a b c d | awk ’{ OFS = ":"; \
    $2 = ""; $6 = "new"
    > print \$0; print NF }’
    
  32. Jeter trois champs (les derniers) en modifiant le nombre de champs.

    
    echo a b c d e f | awk ’\
    { print "NF =", NF;
    > NF = 3; print \$0 }’
    
  33. Il s’agit d’une expression régulière qui définit le séparateur de champ sur l’espace et rien d’autre (correspondance de motifs non gourmande).

    
    FS=[ ]
    
  34. Cela n’affichera que « a ».

    
    echo ' a b c d ' |  awk 'BEGIN { FS = \
    "[ \t\n]+" }
    > { print $2 }'
    
  35. Affiche uniquement la première correspondance de RE (expression régulière).

    
    awk -n '/RE/{p;q;}' file.txt
    
  36. Définit FS à \\

    
    awk -F\\ '...' inputfiles ...
    
  37. Si nous avons un enregistrement comme :
    John Doe
    1234 Unknown Ave.
    Doeville, MA
    Ce script définit le séparateur de champs sur saut de ligne afin qu’il puisse facilement fonctionner sur les lignes.

    
    BEGIN { RS = "" ; FS = "\n" }
    {
    print "Name is:", $1
    print "Address is:", $2
    print "City and State are:", $3
    print ""
    }
    
  38. Avec un fichier à deux champs, les enregistrements seront imprimés comme suit :
    "field1 :field2

    champ3 ; champ4

    …; ..."
    Parce que ORS, le séparateur d’enregistrement de sortie, est défini sur deux sauts de ligne et OFS est « ; ”

    
    awk 'BEGIN { OFS = ";"; ORS = "\n\n" }
    > { print $1, $2 }' inputfile
    
  39. Cela affichera 17 et 18, car la sortie ForMaT est définie pour arrondir les valeurs à virgule flottante à la valeur entière la plus proche.

    
    awk 'BEGIN {
    > OFMT = "%.0f" # print numbers as \
    integers (rounds)
    > print 17.23, 17.54 }'
    
  40. Vous pouvez utiliser printf principalement de la manière dont vous l’utilisez en C.

    
    awk 'BEGIN {
    > msg = "Dont Panic!"
    > printf "%s\n", msg
    >} '
    
  41. Imprime le premier champ sous la forme d’une chaîne de 10 caractères, justifiée à gauche, et de $2 normalement, à côté.

    
    awk '{ printf "%-10s %s\n", $1, \
    $2 }' inputfile
    
  42. Rendre les choses plus jolies.

    
    awk 'BEGIN { print "Name  Number"
                 print "----  ------" }
         { printf "%-10s %s\n", $1, \
    $2 }' inputfile
    
  43. Exemple simple d’extraction de données, où le deuxième champ est écrit dans un fichier nommé « phone-list ».

    
    awk '{ print $2 > "phone-list" }' \
    inputfile
    
  44. Écrivez les noms contenus dans $1 dans un fichier, puis triez et affichez le résultat dans un autre fichier (vous pouvez également ajouter avec >>, comme vous le feriez dans un shell).

    
    awk '{ print $1 > "names.unsorted"
           command = "sort -r > names.sorted"
           print $1 | command }’ inputfile
    
  45. Imprimera 9, 11, 17.

    
    awk 'BEGIN { printf "%d, %d, %d\n", 011, 11, \
    0x11 }'
    
  46. Recherche simple pour foo ou bar.

    
    if (/foo/ || /bar/)
       print "Found!"
    
  47. Opérations arithmétiques simples (la plupart des opérateurs ressemblent beaucoup à C).

    
    awk '{ sum = $2 + $3 + $4 ; avg = sum / 3
    > print $1, avg }' grades
    
  48. Calculatrice simple et extensible.

    
    awk '{ print "The square root of", \
    $1, "is", sqrt($1) }'
    2
    The square root of 2 is 1.41421
    7
    The square root of 7 is 2.64575
    
  49. Imprime tous les enregistrements entre le début et la fin.

    
    awk '$1 == "start", $1 == "stop"' inputfile
    
  50. Les règles BEGIN et END sont exécutées exactement une fois, avant et après tout traitement d’enregistrement.

    
    awk '
    > BEGIN { print "Analysis of \"foo\"" }
    > /foo/ { ++n }
    > END { print "\"foo\" appears", n,\
     "times." }’ inputfile
    
  51. Recherche à l’aide du shell.

    
    echo -n "Enter search pattern: "
    read pattern
    awk "/$pattern/ "'{ nmatches++ }
    END { print nmatches, "found" }' inputfile
    
  52. Conditionnel simple. awk, comme C, prend également en charge les opérateurs ?:.

    
    if (x % 2 == 0)
    print "x is even"
    else
    print "x is odd"
    
  53. Imprime les trois premières trames de chaque enregistrement, une par ligne.

    
    awk '{ i = 1
      while (i <= 3) {
        print $i
        i++
      }
    }’ inputfile
    
  54. Imprime les trois premières trames de chaque enregistrement, une par ligne.

    
    awk '{ for (i = 1; i <= 3; i++)
      print \$i
    }'
    
  55. Quitter avec un code d’erreur différent de 0 signifie que quelque chose ne va pas. Voici un exemple.

    
    BEGIN {
    if (("date" | getline date_now) <= 0) {
      print "Can't get system date" > \
    "/dev/stderr"
      exit 1
    }
    print "current date is", date_now
    close("date")
    }
    
  56. Imprime awk fichier1 fichier2.

    
    awk 'BEGIN {
    > for (i = 0; i < ARGC; i++)
    > print ARGV[i]
    > }’ file1 file2
    
  57. Supprimer des éléments dans un tableau.

    
    for (i in frequencies)
    delete frequencies[i]
    
  58. Recherchez les éléments du tableau.

    
    foo[4] = ""
    if (4 in foo)
    print "This is printed, even though foo[4] \
    is empty"
    
  59. Une variante awk de ctime() en C. C’est ainsi que vous définissez vos propres fonctions dans awk.

    
    function ctime(ts, format)
    {
      format = "%a %b %d %H:%M:%S %Z %Y"
      if (ts == 0)
      ts = systime()
      # use current time as default
      return strftime(format, ts)
    }
    
  60. Un générateur de nombres aléatoires Cliff.

    
    BEGIN { _cliff_seed = 0.1 }
    function cliff_rand()
    {
      _cliff_seed = (100 * log(_cliff_seed)) % 1
      if (_cliff_seed < 0)
        _cliff_seed = - _cliff_seed
      return _cliff_seed
    }
    
  61. Anonymiser un journal Apache (les adresses IP sont aléatoires).

    
    cat apache-anon-noadmin.log | \
    awk 'function ri(n) \
    {  return int(n*rand()); }  \
    BEGIN { srand(); }  { if (! \
    ($1 in randip)) {  \
    randip[$1] = sprintf("%d.%d.%d.%d", \
    ri(255), ri(255)\
    , ri(255), ri(255)); } \
    $1 = randip[$1]; print \$0  }'
    

Conclusion

Comme vous pouvez le voir, avec awk, vous pouvez faire beaucoup de traitement de texte et d’autres choses astucieuses. Nous n’avons pas abordé de sujets plus avancés, comme les fonctions prédéfinies d’awk, mais nous vous en avons montré suffisamment (nous l’espérons) pour commencer à vous en souvenir comme d’un outil puissant.

Articles connexes: