Comment utiliser la commande awk sous Linux
Sous Linux, awk
est une dynamo de manipulation de texte en ligne de commande, ainsi qu'un puissant langage de script. Voici une introduction à certaines de ses fonctionnalités les plus intéressantes.
Sommaire
Comment awk a obtenu son nom
le awk
La commande a été nommée en utilisant les initiales des trois personnes qui ont écrit la version originale en 1977: Alfred Aho, Peter Weinberger et Brian Kernighan. Ces trois hommes appartenaient au légendaire panthéon Unix des Laboratoires Bell AT&T. Avec la contribution de beaucoup d'autres depuis lors, awk
a continué d'évoluer.
Il s'agit d'un langage de script complet, ainsi que d'une boîte à outils de manipulation de texte complète pour la ligne de commande. Si cet article vous met en appétit, vous pouvez consulter tous les détails sur awk
et sa fonctionnalité.
Règles, modèles et actions
awk
fonctionne sur des programmes qui contiennent des règles composées de modèles et d'actions. L'action est exécutée sur le texte qui correspond au modèle. Les motifs sont entourés d'accolades ({}
). Ensemble, un modèle et une action forment une règle. L'ensemble awk
programme est placé entre guillemets simples ('
).
Jetons un œil au type le plus simple de awk
programme. Il n'a pas de motif, il correspond donc à chaque ligne de texte qui y est introduite. Cela signifie que l'action est exécutée sur chaque ligne. Nous l’utiliserons sur la sortie du who
commander.
Voici la sortie standard de who
:
who
Nous n'avons peut-être pas besoin de toutes ces informations, mais souhaitons simplement voir les noms sur les comptes. Nous pouvons diriger la sortie de who
dans awk
, puis dites awk
pour imprimer uniquement le premier champ.
Par défaut, awk
considère un champ comme une chaîne de caractères entourée d'espaces, le début d'une ligne ou la fin d'une ligne. Les champs sont identifiés par un signe dollar ($
) et un certain nombre. Donc, $1
représente le premier champ, que nous utiliserons avec le print
action pour imprimer le premier champ.
Nous tapons ce qui suit:
who | awk '{print $1}'
awk
imprime le premier champ et supprime le reste de la ligne.
Nous pouvons imprimer autant de champs que nous le souhaitons. Si nous ajoutons une virgule comme séparateur, awk
imprime un espace entre chaque champ.
Nous tapons ce qui suit pour imprimer également l'heure à laquelle la personne s'est connectée (champ quatre):
who | awk '{print $1,$4}'
Il existe quelques identificateurs de champ spéciaux. Ceux-ci représentent la ligne de texte entière et le dernier champ de la ligne de texte:
- 0 $: Représente toute la ligne de texte.
- 1 $: Représente le premier champ.
- 2 $: Représente le deuxième champ.
- 7 $: Représente le septième champ.
- 45 $: Représente le 45e champ.
- $ NF: Signifie «nombre de champs» et représente le dernier champ.
Nous allons taper ce qui suit pour faire apparaître un petit fichier texte contenant une courte citation attribuée à Dennis Ritchie:
cat dennis_ritchie.txt
Nous voulons awk
pour imprimer le premier, le deuxième et le dernier champ du devis. Notez que bien qu'il soit enveloppé dans la fenêtre du terminal, il ne s'agit que d'une seule ligne de texte.
Nous tapons la commande suivante:
awk '{print $1,$2,$NF}' dennis_ritchie.txt
Nous ne connaissons pas cette «simplicité». est le 18ème champ dans la ligne de texte, et nous ne nous en soucions pas. Ce que nous savons, c'est que c'est le dernier champ, et nous pouvons utiliser $NF
pour obtenir sa valeur. La période est simplement considérée comme un autre personnage dans le corps du champ.
Ajout de séparateurs de champ de sortie
Vous pouvez également dire awk
pour imprimer un caractère particulier entre les champs au lieu du caractère espace par défaut. La sortie par défaut du date
la commande est un peu particulière car le temps est plongé en plein milieu. Cependant, nous pouvons taper ce qui suit et utiliser awk
pour extraire les champs que nous voulons:
date
date | awk '{print $2,$3,$6}'
Nous utiliserons le OFS
(séparateur de champ de sortie) pour placer un séparateur entre le mois, le jour et l'année. Notez que ci-dessous, nous mettons la commande entre guillemets simples ('
), et non les accolades ({}
):
date | awk 'OFS="/" {print$2,$3,$6}'
date | awk 'OFS="-" {print$2,$3,$6}'
Les règles BEGIN et END
UNE BEGIN
est exécutée une fois avant le début du traitement de texte. En fait, il est exécuté avant awk
lit même n'importe quel texte. Un END
la règle est exécutée une fois tout le traitement terminé. Vous pouvez avoir plusieurs BEGIN
et END
règles, et ils s'exécuteront dans l'ordre.
Pour notre exemple d'un BEGIN
règle, nous imprimerons l'intégralité du devis du dennis_ritchie.txt
fichier que nous avons utilisé précédemment avec un titre au-dessus.
Pour ce faire, nous tapons cette commande:
awk 'BEGIN {print "Dennis Ritchie"} {print $0}' dennis_ritchie.txt
Noter la BEGIN
règle a son propre ensemble d'actions enfermé dans son propre ensemble d'accolades ({}
).
Nous pouvons utiliser cette même technique avec la commande que nous avons utilisée précédemment pour diriger la sortie de who
dans awk
. Pour ce faire, nous tapons ce qui suit:
who | awk 'BEGIN {print "Active Sessions"} {print $1,$4}'
Séparateurs de champ d'entrée
Si tu veux awk
pour travailler avec du texte qui n'utilise pas d'espaces pour séparer les champs, vous devez lui indiquer quel caractère le texte utilise comme séparateur de champ. Par exemple, le /etc/passwd
le fichier utilise deux points (:
) pour séparer les champs.
Nous utiliserons ce fichier et le -F
(chaîne de séparation) option pour dire awk
d'utiliser les deux points (:
) comme séparateur. Nous tapons ce qui suit pour dire awk
pour imprimer le nom du compte utilisateur et du dossier personnel:
awk -F: '{print $1,$6}' /etc/passwd
La sortie contient le nom du compte d'utilisateur (ou le nom de l'application ou du démon) et le dossier de départ (ou l'emplacement de l'application).
Ajout de motifs
Si tout ce qui nous intéresse, ce sont les comptes d'utilisateurs réguliers, nous pouvons inclure un modèle avec notre action d'impression pour filtrer toutes les autres entrées. Étant donné que les numéros d'ID utilisateur sont égaux ou supérieurs à 1 000, nous pouvons baser notre filtre sur ces informations.
Nous tapons ce qui suit pour exécuter notre action d'impression uniquement lorsque le troisième champ ($3
) contient une valeur de 1 000 ou plus:
awk -F: '$3 >= 1000 {print $1,$6}' /etc/passwd
= 1000 {print $ 1, $ 6} '/ etc / passwd "commande dans une fenêtre de terminal." width = "646" height = "147" src = "/ pagespeed_static / 1.JiBnMqyl6S.gif" onload = "pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon (this);" onerror = "this.onerror = null; pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon (this);" />
Le modèle doit précéder immédiatement l'action à laquelle il est associé.
Nous pouvons utiliser le BEGIN
règle pour donner un titre à notre petit rapport. Nous tapons ce qui suit, en utilisant le (n
) notation pour insérer un caractère de nouvelle ligne dans la chaîne de titre:
awk -F: 'BEGIN {print "User Accountsn-------------"} $3 >= 1000 {print $1,$6}' /etc/passwd
= 1000 {print $ 1, $ 6} '/ etc / passwd "commande dans une fenêtre de terminal." width = "646" height = "212" src = "/ pagespeed_static / 1.JiBnMqyl6S.gif" onload = "pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon (this);" onerror = "this.onerror = null; pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon (this);" />
Les motifs sont des expressions régulières à part entière, et ils sont l'une des gloires de awk
.
Supposons que nous voulons voir les identificateurs universellement uniques (UUID) des systèmes de fichiers montés. Si nous recherchons à travers le /etc/fstab
fichier pour les occurrences de la chaîne «UUID», il doit nous renvoyer ces informations.
Nous utilisons le modèle de recherche «/ UUID /» dans notre commande:
awk '/UUID/ {print $0}' /etc/fstab
Il trouve toutes les occurrences de «UUID» et imprime ces lignes. En fait, nous aurions obtenu le même résultat sans le print
car l'action par défaut imprime toute la ligne de texte. Pour plus de clarté, cependant, il est souvent utile d'être explicite. Lorsque vous parcourez un script ou votre fichier d'historique, vous serez heureux d'avoir laissé des indices pour vous-même.
La première ligne trouvée était une ligne de commentaire, et bien que la chaîne "UUID" soit au milieu, awk
encore trouvé. Nous pouvons modifier l'expression régulière et dire awk
pour traiter uniquement les lignes commençant par «UUID». Pour ce faire, nous tapons ce qui suit qui inclut le jeton de début de ligne (^
):
awk '/^UUID/ {print $0}' /etc/fstab
C'est mieux! Maintenant, nous ne voyons que des instructions de montage authentiques. Pour affiner encore plus la sortie, nous tapons ce qui suit et limitons l'affichage au premier champ:
awk '/^UUID/ {print $1}' /etc/fstab
Si nous avions plusieurs systèmes de fichiers montés sur cette machine, nous obtiendrions un tableau soigné de leurs UUID.
Fonctions intégrées
awk
possède de nombreuses fonctions que vous pouvez appeler et utiliser dans vos propres programmes, à partir de la ligne de commande et dans les scripts. Si vous creusez, vous trouverez cela très fructueux.
Pour démontrer la technique générale pour appeler une fonction, nous allons examiner quelques-unes numériques. Par exemple, ce qui suit imprime la racine carrée de 625:
awk 'BEGIN { print sqrt(625)}'
Cette commande affiche l'arctangente de 0 (zéro) et -1 (qui se trouve être la constante mathématique, pi):
awk 'BEGIN {print atan2(0, -1)}'
Dans la commande suivante, nous modifions le résultat de la commande atan2()
fonction avant de l'imprimer:
awk 'BEGIN {print atan2(0, -1)*100}'
Les fonctions peuvent accepter des expressions comme paramètres. Par exemple, voici une façon compliquée de demander la racine carrée de 25:
awk 'BEGIN { print sqrt((2+3)*5)}'
awk Scripts
Si votre ligne de commande se complique ou si vous développez une routine que vous savez que vous voudrez réutiliser, vous pouvez transférer votre awk
commande dans un script.
Dans notre exemple de script, nous allons effectuer toutes les opérations suivantes:
- Indiquez au shell quel exécutable utiliser pour exécuter le script.
- Préparer
awk
utiliser leFS
variable de séparateur de champ pour lire le texte d'entrée avec des champs séparés par des deux-points (:
). - Utilisez le
OFS
séparateur de champ de sortie pour direawk
d'utiliser des deux-points (:
) pour séparer les champs de la sortie. - Réglez un compteur sur 0 (zéro).
- Définissez le deuxième champ de chaque ligne de texte sur une valeur vide (il s'agit toujours d'un «x», nous n'avons donc pas besoin de le voir).
- Imprimez la ligne avec le deuxième champ modifié.
- Incrémentez le compteur.
- Imprime la valeur du compteur.
Notre script est illustré ci-dessous.
le BEGIN
règle effectue les étapes préparatoires, tandis que la END
La règle affiche la valeur du compteur. La règle du milieu (qui n'a pas de nom ni de motif pour correspondre à chaque ligne) modifie le deuxième champ, imprime la ligne et incrémente le compteur.
La première ligne du script indique au shell quel exécutable utiliser (awk
, dans notre exemple) pour exécuter le script. Il passe également le -f
option (nom de fichier) pour awk
, qui l'informe que le texte qu'il va traiter proviendra d'un fichier. Nous transmettrons le nom de fichier au script lorsque nous l'exécuterons.
Nous avons inclus le script ci-dessous sous forme de texte afin que vous puissiez couper et coller:
#!/usr/bin/awk -f BEGIN { # set the input and output field separators FS=":" OFS=":" # zero the accounts counter accounts=0 } { # set field 2 to nothing $2="" # print the entire line print $0 # count another account accounts++ } END { # print the results print accounts " accounts.n" }
Enregistrez-le dans un fichier appelé omit.awk
. Pour rendre le script exécutable, nous tapons ce qui suit en utilisant chmod
:
chmod +x omit.awk
Maintenant, nous allons l'exécuter et passer le /etc/passwd
fichier au script. C'est le dossier awk
traitera pour nous, en utilisant les règles du script:
./omit.awk /etc/passwd
Le fichier est traité et chaque ligne s'affiche, comme illustré ci-dessous.
Les entrées «x» dans le deuxième champ ont été supprimées, mais notez que les séparateurs de champ sont toujours présents. Les lignes sont comptées et le total est donné en bas de la sortie.
awk ne signifie pas maladroit
awk
ne représente pas maladroit; il représente l'élégance. Il a été décrit comme un filtre de traitement et un rédacteur de rapport. Plus précisément, il s'agit des deux, ou plutôt d'un outil que vous pouvez utiliser pour ces deux tâches. En quelques lignes, awk
réalise ce qui nécessite un codage approfondi dans un langage traditionnel.
Cette puissance est exploitée par le concept simple de règles qui contiennent des modèles, qui sélectionnent le texte à traiter et des actions qui définissent le traitement.