Linux sans magie #25 — grep, cut, sort, uniq et wc : extraire et filtrer efficacement du texte

Apprendre à combiner grep, cut, sort, uniq et wc pour filtrer, extraire, trier, compter et résumer des données texte dans des pipelines Linux simples et lisibles.

Dans l’article précédent, nous avons vu comment stdin, stdout, stderr, les redirections et les pipes permettent de faire circuler des données entre les commandes.

Cette fois, nous allons utiliser ce mécanisme pour réaliser un travail très courant sous Linux : prendre un flux texte et le réduire progressivement jusqu’à obtenir l’information utile.

Cinq commandes suffisent déjà pour construire de nombreux traitements pratiques :

  • grep pour sélectionner des lignes ;
  • cut pour extraire des champs ;
  • sort pour trier ;
  • uniq pour regrouper des lignes identiques adjacentes ;
  • wc pour compter.

L’objectif n’est pas d’apprendre une longue liste d’options. Il est de comprendre comment chaque commande transforme un flux, puis comment les assembler dans un pipeline lisible.

Le principe : une commande, une transformation

Un pipeline Unix devient plus facile à comprendre si chaque étape répond à une seule question.

Prenons ce fichier de laboratoire :

2026-09-18 alice INFO connexion
2026-09-18 bob ERROR disque
2026-09-18 alice ERROR réseau
2026-09-18 claire INFO connexion
2026-09-18 bob ERROR disque
2026-09-18 alice INFO déconnexion

Nous allons l’enregistrer dans evenements.log :

cat > evenements.log <<'EOF'
2026-09-18 alice INFO connexion
2026-09-18 bob ERROR disque
2026-09-18 alice ERROR réseau
2026-09-18 claire INFO connexion
2026-09-18 bob ERROR disque
2026-09-18 alice INFO déconnexion
EOF

Le fichier est volontairement simple : les champs sont séparés par des espaces et chaque ligne suit la même structure.

Avant de construire un pipeline, il faut savoir ce que l’on cherche. Par exemple :

Quels utilisateurs apparaissent dans les événements ERROR, et combien de fois chacun apparaît-il ?

Nous pouvons résoudre ce problème étape par étape.

grep : sélectionner les lignes utiles

grep lit du texte et sélectionne les lignes qui correspondent à un motif.

Pour afficher uniquement les erreurs :

grep 'ERROR' evenements.log

Résultat attendu :

2026-09-18 bob ERROR disque
2026-09-18 alice ERROR réseau
2026-09-18 bob ERROR disque

Le point important est que grep ne transforme pas ici les lignes : il décide seulement lesquelles passent à l’étape suivante.

Dans un pipeline, la même commande peut lire depuis stdin :

cat evenements.log | grep 'ERROR'

Cette écriture fonctionne, mais lorsque grep sait lire directement un fichier, la forme suivante est plus simple :

grep 'ERROR' evenements.log

Le pipe devient utile lorsque l’entrée provient réellement d’une autre commande.

Ignorer la casse avec grep -i

L’option -i demande à grep d’ignorer les différences de casse lors de la correspondance.

Exemple :

printf 'Error\nERROR\nerreur\n' | grep -i 'error'

Les deux premières lignes correspondent au motif error sans tenir compte de la casse.

Cette option peut être utile sur des fichiers dont la capitalisation n’est pas homogène.

Exclure des lignes avec grep -v

L’option -v inverse la sélection : elle conserve les lignes qui ne correspondent pas au motif.

Pour éliminer les événements INFO :

grep -v 'INFO' evenements.log

Dans notre fichier, cela revient ici à conserver les événements ERROR.

Le rôle reste le même : grep travaille au niveau de la ligne.

cut : extraire un champ

Après avoir sélectionné les lignes d’erreur, nous voulons uniquement le nom de l’utilisateur.

Dans notre fichier, le deuxième champ contient le nom :

2026-09-18 bob ERROR disque
           ^^^

cut permet de sélectionner un champ lorsqu’un séparateur simple est connu.

Exemple :

cut -d' ' -f2 evenements.log

Ici :

  • -d' ' définit l’espace comme séparateur ;
  • -f2 sélectionne le deuxième champ.

Résultat :

alice
bob
alice
claire
bob
alice

Nous pouvons maintenant combiner grep et cut :

grep 'ERROR' evenements.log | cut -d' ' -f2

Résultat :

bob
alice
bob

Le raisonnement est simple :

grep → conserve les lignes ERROR
cut  → extrait le deuxième champ

Limite importante de cut

cut fonctionne bien lorsque le séparateur est simple et régulier.

Avec -d' ', plusieurs espaces consécutifs peuvent rendre le découpage moins intuitif, car chaque caractère séparateur compte.

Par conséquent, cut est adapté à des formats simples et prévisibles, mais il ne faut pas le présenter comme un parseur universel.

Pour des formats plus complexes ou structurés, d’autres outils sont souvent plus appropriés. Ils restent hors périmètre de cet article.

sort : trier les lignes

Reprenons la sortie précédente :

bob
alice
bob

Pour la trier :

grep 'ERROR' evenements.log | cut -d' ' -f2 | sort

Résultat :

alice
bob
bob

Par défaut, sort trie les lignes selon les règles de comparaison de l’environnement courant.

Pour notre lab avec des noms simples, cela suffit.

Le tri n’est pas seulement esthétique. Il prépare aussi les données pour uniq.

uniq : traiter les doublons adjacents

Une erreur fréquente consiste à penser que uniq cherche tous les doublons n’importe où dans un fichier.

En réalité, uniq travaille sur des lignes identiques adjacentes.

Avec :

bob
alice
bob

un simple :

uniq

ne regrouperait pas les deux lignes bob, car elles ne sont pas voisines.

C’est pourquoi on utilise très souvent :

sort | uniq

Dans notre pipeline :

grep 'ERROR' evenements.log | cut -d' ' -f2 | sort | uniq

Résultat :

alice
bob

Nous avons maintenant la liste des utilisateurs ayant généré au moins un événement ERROR.

Compter les occurrences avec uniq -c

L’option -c ajoute le nombre d’occurrences de chaque groupe de lignes identiques adjacentes.

Exécutez :

grep 'ERROR' evenements.log | cut -d' ' -f2 | sort | uniq -c

Résultat attendu :

      1 alice
      2 bob

Nous avons donc répondu à la question initiale :

  • alice apparaît une fois dans les événements ERROR ;
  • bob apparaît deux fois.

Chaque étape garde une responsabilité précise.

Lire le pipeline de gauche à droite

Le pipeline complet est :

grep 'ERROR' evenements.log | cut -d' ' -f2 | sort | uniq -c

Il faut le lire ainsi :

evenements.log
      ↓
grep 'ERROR'
      ↓
lignes d'erreur uniquement
      ↓
cut -d' ' -f2
      ↓
noms d'utilisateurs
      ↓
sort
      ↓
noms regroupés par ordre
      ↓
uniq -c
      ↓
nombre d'occurrences par utilisateur

Cette méthode de lecture est plus importante que la mémorisation de la ligne complète.

Si le résultat est faux, il suffit d’exécuter le pipeline progressivement jusqu’à trouver l’étape qui ne produit pas ce que l’on attend.

wc : compter des lignes

wc peut compter plusieurs éléments d’un flux. Dans cet article, nous utilisons surtout wc -l, qui compte les lignes.

Pour savoir combien d’événements ERROR sont présents :

grep 'ERROR' evenements.log | wc -l

Résultat :

3

Le fonctionnement est direct :

grep sélectionne trois lignes
        ↓
wc -l compte ces trois lignes

Pour compter le nombre d’utilisateurs distincts ayant produit une erreur :

grep 'ERROR' evenements.log | cut -d' ' -f2 | sort | uniq | wc -l

Résultat :

2

Cette fois, wc -l compte la sortie de uniq, pas celle de grep.

Compter sans perdre le sens du pipeline

Deux pipelines très proches peuvent répondre à deux questions différentes.

Nombre total d’erreurs :

grep 'ERROR' evenements.log | wc -l

Nombre d’utilisateurs distincts concernés :

grep 'ERROR' evenements.log | cut -d' ' -f2 | sort | uniq | wc -l

Le dernier outil est le même, mais les données qui lui arrivent ne sont plus les mêmes.

C’est une règle générale : la signification du résultat dépend de ce que chaque étape a déjà transformé.

Un deuxième exemple : compter les types d’événements

Supposons que nous voulions connaître la fréquence des niveaux INFO et ERROR.

Le niveau est le troisième champ.

Nous pouvons donc écrire :

cut -d' ' -f3 evenements.log | sort | uniq -c

Résultat attendu :

      3 ERROR
      3 INFO

Ici, grep n’est pas nécessaire, car nous voulons conserver toutes les lignes.

Le meilleur pipeline n’est pas celui qui utilise le plus de commandes : c’est celui qui exprime clairement la transformation nécessaire.

Éviter le cat inutile

Une construction fréquente est :

cat evenements.log | grep 'ERROR'

Elle fonctionne, mais grep sait déjà lire directement un fichier :

grep 'ERROR' evenements.log

Cela ne signifie pas que cat est inutile en général.

Il devient pertinent lorsqu’on veut réellement concaténer plusieurs fichiers ou produire un flux dans une situation où cette étape apporte quelque chose.

Le principe à retenir est simplement : ne pas ajouter une commande si elle n’effectue aucune transformation utile.

Diagnostiquer un pipeline étape par étape

Lorsqu’un pipeline devient plus long, évitez de corriger toute la ligne à l’aveugle.

Commencez par la première étape :

grep 'ERROR' evenements.log

Puis ajoutez la suivante :

grep 'ERROR' evenements.log | cut -d' ' -f2

Puis :

grep 'ERROR' evenements.log | cut -d' ' -f2 | sort

Puis enfin :

grep 'ERROR' evenements.log | cut -d' ' -f2 | sort | uniq -c

Cette progression permet de vérifier le contenu du flux après chaque transformation.

C’est particulièrement utile lorsqu’un fichier réel contient des séparateurs inattendus, des lignes vides ou des formats hétérogènes.

Bonnes pratiques

Gardez les pipelines courts et lisibles.

Si une chaîne devient difficile à comprendre, testez ou documentez chaque étape séparément.

Ne supposez pas qu’un fichier texte est parfaitement régulier. Avant d’utiliser cut, examinez quelques lignes :

head evenements.log

Vérifiez également si les espaces, tabulations ou délimiteurs sont homogènes.

Pour uniq, retenez la règle fondamentale : les lignes identiques doivent être adjacentes pour être regroupées. Si vous cherchez des valeurs uniques dans un flux non trié, sort | uniq est une construction courante.

Enfin, distinguez toujours le nombre total de lignes du nombre de valeurs distinctes. wc -l compte uniquement ce qu’il reçoit.

Sécurité et limites

Les commandes utilisées ici sont essentiellement des outils de lecture et de transformation de texte.

Elles deviennent toutefois capables de modifier des fichiers si leur sortie est redirigée avec > ou >>.

Par exemple :

grep 'ERROR' evenements.log > erreurs.log

crée ou remplace erreurs.log.

Comme vu dans l’article précédent, vérifiez donc toujours la destination d’une redirection avant d’utiliser un fichier important.

Évitez aussi d’utiliser des pipelines textuels naïfs pour traiter des formats structurés complexes lorsque la structure elle-même doit être respectée. Un fichier JSON, YAML ou CSV avec échappements et guillemets mérite généralement un outil adapté à son format.

Ce que nous ne couvrons pas encore

Nous restons volontairement sur les fonctions essentielles.

Nous ne détaillons pas ici :

  • les expressions régulières avancées ;
  • grep -P et les particularités PCRE ;
  • awk ;
  • sed ;
  • les clés de tri avancées de sort ;
  • les règles de locale en profondeur ;
  • les séparateurs complexes ;
  • le traitement robuste de CSV, JSON ou YAML ;
  • les pipelines sophistiqués de plusieurs dizaines d’étapes.

Le but est de maîtriser d’abord les briques de base et leur circulation dans un pipeline.

Nettoyage du lab

Si vous avez travaillé dans un répertoire dédié, supprimez simplement le fichier créé :

rm -f evenements.log

Si d’autres fichiers de test ont été créés, vérifiez leur nom avant suppression.

Références officielles

Conclusion

grep, cut, sort, uniq et wc deviennent réellement utiles lorsqu’on les considère comme des transformations successives plutôt que comme des commandes isolées.

Le modèle de base est simple :

grep → choisir les lignes
cut  → choisir les champs
sort → ordonner
uniq → regrouper les doublons adjacents
wc   → compter

Un pipeline comme :

grep 'ERROR' evenements.log | cut -d' ' -f2 | sort | uniq -c

n’est alors plus une formule à mémoriser. C’est une succession de décisions lisibles : filtrer les erreurs, extraire l’utilisateur, regrouper les noms identiques puis compter leurs occurrences.

Cette manière de raisonner constitue une base solide avant d’aborder des outils de traitement de texte plus puissants.