ENSI-II2 Environnement Unix

Partie I : AWK Exercice 1 Question 1 - Afficher la nième ligne d'un fichier Pour afficher une ligne spécifique (par exemple, la 5ème ligne), nous utilisons la variable interne NR (Number of Record) qui stocke le numéro de la ligne courante.

D'après le document ENSI-II2 Environnement Unix

Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

ENSI-II2 Environnement Unix

Document source

ENSI-II2 Environnement Unix

Programming, Unix, AWK, SED · PDF · 4 pages

Afficher l'aperçu du document

Consulter le document original →

Partie I : AWK

Exercice 1

Question 1 - Afficher la nième ligne d'un fichier

Pour afficher une ligne spécifique (par exemple, la 5ème ligne), nous utilisons la variable interne NR (Number of Record) qui stocke le numéro de la ligne courante.

awk 'NR == 5' fichier

Question 2 - Compter le nombre de mots d'un fichier

La variable interne NF (Number of Fields) contient le nombre de champs (mots par défaut) de la ligne courante. Nous pouvons les additionner dans une variable et afficher le total à la fin.

awk '{ mots += NF } END { print mots }' fichier

Question 3 - Afficher les lignes de plus de 80 caractères

La fonction length($0) renvoie la longueur totale de la ligne courante. L'action par défaut d'awk étant d'afficher la ligne (print), il suffit de définir la condition.

awk 'length($0) > 80' fichier

Question 4 - Afficher les lignes qui contiennent exactement deux champs

Nous utilisons à nouveau la variable NF en la comparant avec la valeur 2.

awk 'NF == 2' fichier

Question 5 - Afficher la liste des champs de chaque ligne dans un ordre inversé

Il faut parcourir les champs de chaque ligne en partant du dernier (NF) jusqu'au premier (1), en utilisant la fonction printf pour éviter les retours à la ligne après chaque champ, puis afficher un saut de ligne avec print "".

awk '{
    for (i = NF; i > 0; i--) {
        printf "%s ", $i
    }
    print ""
}' fichier

Question 6 - Compter le nombre de lignes qui contiennent la chaîne "l2ti"

Nous incrémentons une variable à chaque fois que la chaîne correspond à l'expression régulière /l2ti/. Le +0 dans le bloc END garantit l'affichage de 0 si aucune ligne ne correspond (au lieu d'un affichage vide).

awk '/l2ti/ { count++ } END { print count+0 }' fichier

Question 7 - Afficher toutes les lignes dont le premier champ est différent de celui de la ligne précédente

Nous comparons le premier champ $1 avec une variable qui stocke le premier champ de la ligne précédente. Si c'est différent, nous affichons la ligne, puis nous mettons à jour la variable.

awk '$1 != prev { print } { prev = $1 }' fichier

Exercice 2 - Mots avec trois lettres majuscules adjacentes ou plus

L'énoncé demande d'afficher les mots. Il faut donc examiner chaque champ de chaque ligne. L'expression régulière /[A-Z][A-Z][A-Z]/ vérifie la présence d'au moins trois majuscules consécutives.

#!/usr/bin/awk -f
{
    for (i = 1; i <= NF; i++) {
        if ($i ~ /[A-Z][A-Z][A-Z]/) {
            print $i
        }
    }
}

Exercice 3 - Fichiers accédés uniquement en lecture par les autres utilisateurs

Pour obtenir les permissions, nous couplons awk à la commande ls -l. Le motif des permissions correspond à 10 caractères. "Uniquement en lecture par les autres" signifie que les 8ème, 9ème et 10ème caractères doivent être r, - et -.

ls -l | awk '/^.......r--/ { print $9 }'

Note : Le 9ème champ ($9) correspond au nom du fichier dans la sortie standard de ls -l sur la plupart des systèmes Unix.

Exercice 4 - Dates de connexion des propriétaires des fichiers portant la permission de lecture pour les autres

La permission "lecture pour les autres" signifie que le 8ème caractère des droits est un r. Le propriétaire se trouve dans le 3ème champ ($3). Nous mémorisons les propriétaires vus dans un tableau vu pour ne pas lancer la commande last plusieurs fois pour le même utilisateur. La fonction system() permet à awk d'exécuter une commande shell.

ls -l | awk '/^.......r../ { 
    if (!vu[$3]++) { 
        system("last " $3) 
    } 
}'

Exercice 5 - Lignes dont le premier champ est différent de celui de la ligne précédente

Cette question est une répétition exacte de l'Exercice 1, Question 7 du sujet source. La commande est strictement la même :

awk '$1 != prev { print } { prev = $1 }' fichier

Exercice 6 - Simuler la commande "uniq" en éliminant les lignes redondantes et vides

La commande classique uniq ne filtre que les doublons adjacents. La question ajoute également l'élimination des lignes vides (NF == 0).

#!/usr/bin/awk -f
# On ignore les lignes vides
NF == 0 { next }

# Si la ligne entière ($0) est différente de la précédente, on l'affiche
$0 != prev { 
    print $0
    prev = $0 
}

Alternative : Si l'énoncé sous-entendait une suppression globale des doublons (peu importe leur position dans le fichier), le code court classique serait : awk 'NF > 0 && !vu[$0]++' fichier.

Exercice 7 - Vérification du nombre de champs par enregistrement

Le script doit définir : comme séparateur, lire le nombre de champs de la première ligne, puis comparer chaque ligne suivante à cette référence.

Fichier count.awk :

BEGIN {
    FS = ":"
    erreurs = 0
}

# Traitement de la toute première ligne
NR == 1 {
    attendu = NF
    print "Chaque enregistrement doit comporter " attendu " champs"
}

# Traitement de toutes les lignes (y compris la première, qui passera forcément ce test)
{
    if (NF != attendu) {
        print "Enregistrement " NR " a " NF " champs"
        erreurs++
    }
}

# Traitement à la fin du fichier
END {
    print "Le fichier " FILENAME " possède " NR " enregistrements"
    if (erreurs > 0) {
        print "Le fichier " FILENAME " comporte " erreurs " enregistrement(s) erroné(s)"
    } else {
        print "Tous les enregistrements sont corrects."
    }
}

Exécution : awk -f count.awk test ou awk -f count.awk /etc/passwd produira exactement la sortie demandée par l'énoncé.

Partie II : SED

Question 1 - Afficher des lignes contenant trois majuscules successives

L'option -n supprime l'affichage par défaut de sed, et la commande p force l'affichage uniquement pour les lignes validant le motif.

sed -n '/[A-Z]\{3\}/p' fichier

Note : /[A-Z][A-Z][A-Z]/ est également correct.

Question 2 - Remplacer les mots Computer ou comuter par COMPUTER

Nous respectons l'orthographe de la source (le mot "comuter" est explicitement mentionné). Le drapeau g à la fin indique un remplacement global sur toute la ligne.

sed 's/\(Computer\|comuter\)/COMPUTER/g' fichier

Question 3 - Encadrer le premier nombre de chaque ligne avec des **

Un nombre s'exprime par une série de chiffres : [0-9]\+ ou [0-9][0-9]*. Le symbole & dans la zone de remplacement fait référence à la chaîne qui a été trouvée. Sans le drapeau g, seul le premier nombre de la ligne est impacté.

sed 's/[0-9][0-9]*/**&**/' fichier

Question 4 - Afficher un fichier à partir de la onzième ligne

L'intervalle de lignes 11,$ désigne la 11ème ligne jusqu'à la fin ($) du fichier. L'option -n et la commande p n'affichent que cette zone.

sed -n '11,$p' fichier

Question 5 - Imprimer les lignes commençant par le mot From

L'accent circonflexe ^ sert d'ancre pour désigner le début de la ligne.

sed -n '/^From/p' fichier

Question 6 - Supprimer les lignes contenant une chaîne donnée

La commande d sert à détruire (supprimer) l'espace de travail pour la ligne courante correspondant au motif. Remplaçons "chaine" par le texte désiré.

sed '/chaine/d' fichier

Question 7 - Supprimer les lignes ne contenant pas une chaîne donnée

Le point d'exclamation ! permet d'inverser la logique d'une commande. Ici, il applique la commande de suppression (d) à toutes les lignes ne validant pas le motif.

sed '/chaine/!d' fichier

Question 8 - Significations des commandes de remplacement

  • sed "s/toto/TOTO/" fichier Remplace uniquement la première occurrence de la chaîne "toto" par "TOTO" sur chaque ligne parcourue.
  • sed "s/toto/TOTO/3" fichier Remplace spécifiquement la troisième occurrence de la chaîne "toto" par "TOTO" sur chaque ligne (les 1ère et 2ème restent intactes).
  • sed "s/toto/TOTO/g" fichier Remplace toutes les occurrences ("g" pour global) de la chaîne "toto" par "TOTO" sur toute la ligne.
  • sed "s/toto/TOTO/w resultat" fichier Remplace la première occurrence de "toto" par "TOTO" sur chaque ligne et écrit (sauvegarde) spécifiquement les lignes qui ont subi une modification dans le fichier externe nommé resultat, tout en continuant d'afficher la sortie standard.

Question 9 - Inverser l'ordre de la première et la deuxième colonne d'un fichier

Nous utilisons les parenthèses capturantes \( et \) pour conserver les colonnes, et \1 et \2 pour les rappeler. En supposant que les colonnes soient séparées par des espaces ou tabulations ([^ \t]\+ représente un bloc de texte sans espace).

sed 's/^\([^ \t]\+\)\([ \t]\+\)\([^ \t]\+\)/\3\2\1/' fichier

Note : Une version simplifiée considérant de simples espaces serait : sed 's/^\([^ ]*\) *\([^ ]*\)/\2 \1/' fichier

Question 10 - Entourer chaque nombre contenu dans un fichier par deux a

Comme pour la question 3, & représente le nombre trouvé. L'ajout de g force sed à faire le remplacement sur tous les nombres de la ligne, et non juste le premier.

sed 's/[0-9][0-9]*/a&a/g' fichier

Question 11 - N'afficher que les lignes contenant le nombre 55 d'un fichier donné

Pour s'assurer d'avoir le nombre 55 strict (et ne pas déclencher sur 155 ou 555), il est recommandé d'utiliser des frontières de mots \b.

sed -n '/\b55\b/p' fichier

Si l'enseignant attend la version sed basique sans contrainte de mot, la syntaxe classique est : sed -n '/55/p' fichier.

Méthode

Face à ce type de sujet évaluant la maîtrise d'outils d'extraction textuelle comme awk et sed, voici l'approche à adopter :

  1. Distinguer la portée du filtre : Demandez-vous toujours si l'opération doit s'appliquer à l'ensemble du fichier (remplacement global : drapeau g pour sed, boucle for pour awk) ou uniquement au premier élément d'une ligne.
  2. Identifier l'outil optimal :
    • sed est idéal pour les substitutions (s/.../.../) et les affichages ou suppressions simples basés sur un contexte de ligne entière (/motif/d, 11,$p).
    • awk brille dès qu'il est question de colonnes (champs délimités) et d'arithmétique (comptage de mots avec NF, suivi de variables count, manipulations de variables internes).
  3. Comprendre les structures implicites : En awk, une instruction structurée comme condition { action } applique l'action à chaque ligne vérifiant la condition. S'il n'y a pas d'action (ex : awk 'length($0) > 80'), l'action par défaut est toujours l'affichage de la ligne courante ({ print }).
  4. Maîtriser les regex classiques : Il est impératif de connaître le fonctionnement des classes ([A-Z], [0-9]), des quantificateurs (*, \+, \{3\}) et des ancres (^ pour début de ligne). La justesse de vos scripts dépend de la précision de vos expressions régulières.

Partager

Commentaires

Aucun commentaire pour le moment. Posez la première question.

Les commentaires sont relus avant publication. Votre e-mail n'est jamais affiché.

← Toutes les révisions