awkCommencer avec awk


Remarques

Le nom AWK provient des dernières initiales de ses créateurs Alfred V. Aho, Peter J. Weinberger et
Brian W. Kernighan.

Ressources

Versions

prénom Version initiale Version Date de sortie
POSIX awk 1992 Norme IEEE 1003.1, édition 2013 2013-04-19
Un vrai Awk ou nawk ou BWK awk 198X - 2012-12-20
GNU awk ou gawk 1986 4.1.3 2015-05-19

AWK par des exemples

AWK est un langage de manipulation de chaînes, largement utilisé dans les systèmes UNIX. L'idée derrière AWK était de créer un langage polyvalent à utiliser pour travailler sur des fichiers, ce qui n'était pas trop complexe à comprendre.

AWK a d'autres variantes, mais le concept principal est le même, avec seulement des fonctionnalités supplémentaires. Ces autres variantes sont NAWK et GAWK. GAWK contient toutes les fonctionnalités des deux, tandis que NAWK est une étape au-dessus d’AWK, si vous le souhaitez.

La manière la plus simple de penser à AWK est de considérer qu’elle comporte deux parties principales. Le motif et l'action.

Probablement l'exemple le plus fondamental d'AWK: (Voir aussi: Hello World)

BEGIN {print "START"}
      {print        }
END   {print "STOP" }
 

Ici, les mots-clés BEGIN et END sont le motif, tandis que l'action est à l'intérieur du {}. Cet exemple serait inutile, mais il suffirait de changements mineurs pour que cela devienne une fonction utile.

BEGIN {print "File\tAuthor"}
      {print $8, "\t", $3}
END {print " - DONE - "}
 

Ici, \t représente un caractère Tab et est utilisé pour égaliser les limites de la ligne de sortie. $ 8 et $ 3 sont similaires à ceux utilisés dans les Shell Scripts , mais au lieu d'utiliser les arguments 3 et 8, ils utilisent les 3ème et 8ème colonnes de la ligne de saisie.

Ainsi, cet exemple affichera: Auteur de fichier sur la ligne supérieure, tandis que la deuxième ligne concerne les chemins de fichier. $ 8 est le nom du fichier, $ 3 est le propriétaire (en regardant le chemin du répertoire, cela sera plus clair). Enfin, la ligne du bas imprime, comme vous vous en doutez, - DONE -

Crédit pour l'exemple ci-dessus va à http://www.grymoire.com/Unix/Awk.html

Fichier de référence

coins.txt de Greg Goebel:

gold     1    1986  USA                 American Eagle
gold     1    1908  Austria-Hungary     Franz Josef 100 Korona
silver  10    1981  USA                 ingot
gold     1    1984  Switzerland         ingot
gold     1    1979  RSA                 Krugerrand
gold     0.5  1981  RSA                 Krugerrand
gold     0.1  1986  PRC                 Panda
silver   1    1986  USA                 Liberty dollar
gold     0.25 1986  USA                 Liberty 5-dollar piece
silver   0.5  1986  USA                 Liberty 50-cent piece
silver   1    1987  USA                 Constitution dollar
gold     0.25 1987  USA                 Constitution 5-dollar piece
gold     1    1988  Canada              Maple Leaf
 

Théorie minimale

General awk one-liner:

awk <awk program> <file>
 

ou:

<shell-command> | awk <awk program> 
 

<shell-command> et <file> sont adressés en entrée awk .

<awk program> est un code suivant ce template (simple, pas double, guillemets):

'BEGIN   {<init actions>};
 <cond1> {<program actions>};
 <cond2> {<program actions>};
 ...
 END  {<final actions>}'
 

où:

  • <condX> condition <condX> est le plus souvent une expression régulière /re/ , à associer aux lignes d'entrée awk;
  • <* actions> sont des séquences d' instructions , similaires aux commandes shell, équipées de constructions de type C.

`` est traité selon les règles suivantes:
  1. BEGIN ... et END ... sont facultatifs et exécutés avant ou après le traitement des lignes d'entrée awk.
  2. Pour chaque ligne de l'entrée awk, si la condition <condN> est viande, le bloc <program actions> associé est exécuté.
  3. {<program actions>} défini par défaut sur {print $0} .

Les conditions peuvent être combinées avec des opérateurs logiques standard:

    /gold/ || /USA/ && !/1986/
 

&& a priorité sur || ;

La déclaration d' print . print item1 item2 éléments sur STDOUT.
Les éléments peuvent être des variables ( X , $0 ), des chaînes ("hello") ou des nombres.
item1, item2 sont regroupés avec la valeur de la variable OFS ;
item1 item2 sont justapoxés ! Utilisez item1 " " item2 pour les espaces ou printf pour plus de fonctionnalités.

Les variables n'ont pas besoin de $ , c'est-à-dire: print myVar;
Les variables spéciales suivantes sont intégrées à awk:

  • FS : agit comme séparateur de champs pour séparer les lignes d'entrée awk dans les champs. Je peux être un seul caractère, FS="c" ; une chaîne FS="" , FS="" (alors chaque caractère devient un champ séparé); une expression régulière sans barres obliques, FS="re" ; FS=" " signifie des exécutions d'espaces et d'onglets et est la valeur par défaut.
  • NF : le nombre de champs à lire
  • $1 $2 , ...: 1er champ, 2e champ. etc. de la ligne d'entrée actuelle,
  • $0 : ligne d'entrée actuelle;
  • NR : numéro de la ligne de vente actuelle.
  • OFS : chaîne pour assembler les champs lors de l'impression.
  • ORS : séparateur d'enregistrement de sortie, par défaut une nouvelle ligne.
  • RS : séparateur de ligne d'entrée (enregistrement). Par défaut à newline. Définir comme FS .
  • IGNORECASE : affecte FS et RS lorsque sont des expressions régulières;

Exemples

Filtrer les lignes en regexp gold et les compter:

# awk 'BEGIN {print "Coins"} /gold/{i++; print $0}  END {print i " lines out of " NR}' coins.txt
Coins
gold     1    1986  USA                 American Eagle      
gold     1    1908  Austria-Hungary     Franz Josef 100 Korona 
gold     1    1984  Switzerland         ingot 
gold     1    1979  RSA                 Krugerrand 
gold     0.5  1981  RSA                 Krugerrand 
gold     0.1  1986  PRC                 Panda                       
gold     0.25 1986  USA                 Liberty 5-dollar piece
gold     0.25 1987  USA                 Constitution 5-dollar piece
gold     1    1988  Canada              Maple Leaf
9 lines out of 13
 

Action par défaut print $0 et condition basée sur la variable interne awk NR :

# awk 'BEGIN {print "First 3 coins"} NR<4' coins.txt
First 3 coins                                                  
gold     1    1986  USA                 American Eagle         
gold     1    1908  Austria-Hungary     Franz Josef 100 Korona 
silver  10    1981  USA                 ingot
 
Formatage avec le style `printf`:
# awk '{printf ("%s \t %3.2f\n", $1, $2)}' coins.txt
gold     1.00                                      
gold     1.00                                      
silver   10.00                                     
gold     1.00                                      
gold     1.00                                      
gold     0.50                                      
gold     0.10                                      
silver   1.00                                      
gold     0.25                                      
silver   0.50                                      
silver   1.00                                      
gold     0.25                                      
gold     1.00
 

Exemples de condition

awk 'NR % 6'            # prints all lines except those divisible by 6
awk 'NR > 5'            # prints from line 6 onwards (like tail -n +6, or sed '1,5d')
awk '$2 == "foo"'       # prints lines where the second field is "foo"
awk '$2 ~ /re/'         # prints lines where the 2nd field mateches the regex /re/
awk 'NF >= 6'           # prints lines with 6 or more fields
awk '/foo/ && !/bar/'   # prints lines that match /foo/ but not /bar/
awk '/foo/ || /bar/'    # prints lines that match /foo/ or /bar/ (like grep -e 'foo' -e 'bar')
awk '/foo/,/bar/'       # prints from line matching /foo/ to line matching /bar/, inclusive
awk 'NF'                # prints only nonempty lines (or: removes empty lines, where NF==0)
awk 'NF--'              # removes last field and prints the line
 

En ajoutant une action {...} on peut imprimer un champ spécifique, plutôt que la ligne entière, par exemple:

awk '$2 ~ /re/{print $3 " " $4}'
 

imprime les troisième et quatrième champs de lignes où le second champ correspond à l'expression rationnelle / re /.

Quelques fonctions de chaîne

substr() :

# awk '{print substr($3,3) " " substr($4,1,3)}' 
86 USA                                            
08 Aus                                            
81 USA                                            
84 Swi                                            
79 RSA                                            
81 RSA                                            
86 PRC                                            
86 USA                                            
86 USA                                            
86 USA                                            
87 USA                                            
87 USA                                            
88 Can                                            
 

match(s, r [, arr]) renvoie la position dans s où l'expression rationnelle r apparaît et définit les valeurs de RSTART et RLENGTH . Si l'argument arr est fourni, il renvoie le tableau arr où les éléments sont définis sur la sous-expression entre parenthèses correspondante. Le 0ème élément correspondant à arr est défini sur l'intégralité de la correspondance regex. Les expressions arr[n, "start"] et arr[n, "length"] fournissent également la position de départ et la longueur de chaque sous-chaîne correspondante.

Plus de fonctions de chaîne:

sub(/regexp/, "newstring"[, target])
gsub(/regexp/, "newstring"[, target])
toupper("string")
tolower("string")
 

Déclarations

Une simple déclaration est souvent l'une des suivantes:

variable = expression 
print [ expression-list ] 
printf format [ , expression-list ] 
next # skip remaining patterns on this input line
exit # skip the rest of the input
 

Si stat1 et stat2 sont des instructions, les instructions suivantes sont également disponibles:

{stat}

{stat1;  stat2}

{stat1 
stat2}

if ( conditional ) statement [ else statement ]
 

Les constructions de type C standard suivantes sont des instructions:

if ( conditional ) statement [ else statement ]
while ( conditional ) statement
for ( expression ; conditional ; expression ) statement
break    # usual C meaning 
continue # usual C meaning 
 

Une boucle de style C pour imprimer l'élément de description de longueur variable, en commençant par le champ 4:

# awk '{out=""; for(i=4;i<=NF;i++){out=out" "$i}; print out}' coins.txt
USA American Eagle                    
Austria-Hungary Franz Josef 100 Korona
USA ingot                             
Switzerland ingot                     
RSA Krugerrand                        
RSA Krugerrand                        
PRC Panda                             
USA Liberty dollar                    
USA Liberty 5-dollar piece            
USA Liberty 50-cent piece             
USA Constitution dollar               
USA Constitution 5-dollar piece       
Canada Maple Leaf
 

Notez que i est initialisé à 0.

Si les conditions et les calculs sont appliqués aux champs nunériques:

# awk '/gold/ {if($3<1980) print $0 "$" 425*$2}' coins.txt    
gold     1    1908  Austria-Hungary     Franz Josef 100 Korona      $425
gold     1    1979  RSA                 Krugerrand                  $425   
 

Script exécutable AWK

#!/usr/bin/gawk -f
# This is a comment
(pattern) {action}
...
 

Passer des variables de shell

# var="hello"
# awk -v x="$var" 'BEGIN {print x}'
hello
 

Bonjour le monde

L'exemple Hello World est aussi simple que:

awk 'BEGIN {print "Hello world"}'
 

Le programme awk plus élémentaire consiste en une valeur vraie (typiquement 1 ) et fait que awk répète ses entrées:

$ date | awk '1'
Mon Jul 25 11:12:05 CEST 2016
 

Puisque "bonjour monde" est aussi une vraie valeur, vous pouvez également dire:

$ date | awk '"hello world"'
Mon Jul 25 11:12:05 CEST 2016
 

Cependant, votre intention devient beaucoup plus claire si vous écrivez

$ date | awk '{print}'
Mon Jul 25 11:12:05 CEST 2016
 

au lieu.

Comment exécuter les programmes AWK

Si le programme est court, vous pouvez l'inclure dans la commande qui exécute awk:

awk -F: '{print $1, $2}' /etc/passwd
 

Dans cet exemple, en utilisant le commutateur de ligne de commande -F: nous recommandons à awk d’utiliser: comme délimiteur de champs d’entrée. Est-ce la même chose

awk 'BEGIN{FS=":"}{print $1,$2}' file
 

Autrement, nous pouvons enregistrer tout le code awk dans un fichier awk et appeler ce programme awk comme ceci:

awk -f 'program.awk' input-file1 input-file2 ...
 

program.awk peut être n'importe quel programme multiligne, à savoir:

# file print_fields.awk
BEGIN {print "this is a header"; FS=":"}
{print $1, $2}
END {print "that was it"}
 

Et ensuite l'exécuter avec:

awk -f print_fields.awk /etc/passwd   #-f advises awk which program file to load
 

Ou plus généralement:

awk -f program-file input-file1 input-file2 ...
 

L'avantage d'avoir le programme dans un fichier séparé est que vous pouvez écrire le programme avec une identification correcte pour vous aider, vous pouvez inclure des commentaires avec #, etc.