DevOpsFacile
AccueilParcours de formationCertificationsModulesCheat SheetÀ Propos
DevOpsFacile

Une plateforme d'apprentissage complète pour maîtriser les pratiques DevOps modernes, du débutant à l'expert.

contact@devopsfacile.fr

Formation

  • Parcours de formation
  • Modules

Informations

  • À Propos
  • Conditions d'utilisation
  • Confidentialité
  • Mentions légales

© 2026 DevOps Facile. Tous droits réservés.

Fait avec pour la communauté DevOps

ModulesScripting Bash et administration système Linux11 - Traitement de texte avancé avec awk et sed

Détails

  • 40 minutes
  • Avancé

Objectifs

  • Utiliser awk pour traiter des fichiers structurés (CSV, logs)
  • Écrire des programmes awk avec règles BEGIN, END et conditions
  • Utiliser sed pour des transformations complexes avec expressions régulières
  • Combiner awk et sed dans des pipelines de traitement de données
Module Scripting Bash et administration système Linux

Exercice 11 : Traitement de texte avancé avec awk et sed

🎯 Objectifs

À la fin de cet exercice, vous serez capable de :

  • ✅ Utiliser awk pour extraire, filtrer et calculer sur des colonnes
  • ✅ Écrire des programmes awk avec BEGIN, END, conditions et variables
  • ✅ Utiliser sed pour des substitutions, insertions et suppressions
  • ✅ Enchaîner grep | awk | sed | sort | uniq dans des pipelines efficaces
  • ✅ Analyser des fichiers de log réels avec ces outils

Durée estimée : 40 minutes

Difficulté : ⭐⭐⭐☆☆ (Avancé)

Prérequis : Exercice 05 (pipes et texte) complété, notion de regex


📖 Contexte

awk et sed sont les couteaux suisses du traitement de texte Linux. En DevOps, ils servent à analyser des logs, transformer des configurations, générer des rapports et traiter des fichiers CSV exportés depuis des outils de monitoring. Maîtriser ces deux outils permet de faire en une ligne ce qui prendrait 50 lignes de Python.


📋 Énoncé

Analysez des logs d'accès web et des fichiers de configuration avec awk et sed.


🧭 Déroulement de l'exercice

Tâche 1 : Fondamentaux awk

bash
# Créer un CSV de test
cat > serveurs.csv << 'EOF'
nom,ip,cpu,memoire,statut
web-01,10.0.1.1,45,72,ok
web-02,10.0.1.2,88,65,ok
db-01,10.0.2.1,23,91,ok
db-02,10.0.2.2,95,89,alerte
cache-01,10.0.3.1,12,45,ok
backup-01,10.0.4.1,5,30,maintenance
EOF

# Afficher les colonnes 1 et 5 (nom et statut)
awk -F',' '{print $1, $5}' serveurs.csv

# Ignorer l'en-tête (NR = numéro de ligne)
awk -F',' 'NR > 1 {print $1, $5}' serveurs.csv

# Filtrer les serveurs en alerte ou maintenance
awk -F',' 'NR > 1 && ($5 == "alerte" || $5 == "maintenance")' serveurs.csv

# Calculer la moyenne CPU
awk -F',' 'NR > 1 {total += $3; nb++} END {printf "CPU moyen : %.1f%%\n", total/nb}' serveurs.csv

# Compter par statut
awk -F',' 'NR > 1 {count[$5]++} END {for (s in count) print s": "count[s]}' serveurs.csv

Vérification : La moyenne CPU doit être calculée et les statuts comptés.


Tâche 2 : Analyse de logs Apache/Nginx

bash
# Générer un faux fichier de log (format Combined Log Format)
cat > access.log << 'EOF'
192.168.1.1 - - [29/Apr/2025:10:00:01 +0000] "GET /api/users HTTP/1.1" 200 1234 "-" "Mozilla/5.0"
192.168.1.2 - - [29/Apr/2025:10:00:02 +0000] "POST /api/login HTTP/1.1" 401 89 "-" "curl/7.68"
192.168.1.1 - - [29/Apr/2025:10:00:03 +0000] "GET /api/products HTTP/1.1" 200 5678 "-" "Mozilla/5.0"
10.0.0.5 - - [29/Apr/2025:10:00:04 +0000] "GET /admin HTTP/1.1" 403 45 "-" "Python-urllib/3.9"
192.168.1.3 - - [29/Apr/2025:10:00:05 +0000] "GET /api/users HTTP/1.1" 200 1234 "-" "Mozilla/5.0"
10.0.0.5 - - [29/Apr/2025:10:00:06 +0000] "GET /etc/passwd HTTP/1.1" 404 23 "-" "Python-urllib/3.9"
192.168.1.2 - - [29/Apr/2025:10:00:07 +0000] "POST /api/login HTTP/1.1" 200 567 "-" "curl/7.68"
192.168.1.4 - - [29/Apr/2025:10:00:08 +0000] "GET /api/products HTTP/1.1" 500 12 "-" "Mozilla/5.0"
10.0.0.5 - - [29/Apr/2025:10:00:09 +0000] "GET /.env HTTP/1.1" 404 23 "-" "Python-urllib/3.9"
192.168.1.1 - - [29/Apr/2025:10:00:10 +0000] "DELETE /api/users/42 HTTP/1.1" 204 0 "-" "Mozilla/5.0"
EOF

echo "=== Top 3 des IPs les plus actives ==="
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -3

echo ""
echo "=== Codes HTTP par fréquence ==="
awk '{print $9}' access.log | sort | uniq -c | sort -rn

echo ""
echo "=== Requêtes suspectes (user-agent Python) ==="
awk '$12 ~ /Python/' access.log | awk '{print $1, $7, $9}'

echo ""
echo "=== Taille totale transférée par IP ==="
awk '{bytes[$1] += $10} END {
  for (ip in bytes)
    printf "%s : %d octets\n", ip, bytes[ip]
}' access.log | sort -t: -k2 -rn

echo ""
echo "=== Rapport de sécurité ==="
awk 'BEGIN {
  print "IP\t\tTentatives\tURLs suspectes"
  print "---\t\t----------\t--------------"
}
$9 >= 400 {
  tentatives[$1]++
}
$7 ~ /passwd|shadow|\.env|\.git/ {
  suspects[$1]++
}
END {
  for (ip in tentatives)
    printf "%s\t%d\t\t%d\n", ip, tentatives[ip], suspects[ip]+0
}' access.log

Tâche 3 : sed pour les transformations

bash
# Fichier de configuration à transformer
cat > app.conf << 'EOF'
# Configuration de l'application
database_host=localhost
database_port=5432
database_name=myapp_dev
database_user=developer
log_level=DEBUG
api_url=http://localhost:8080
workers=2
# Fin de configuration
EOF

echo "=== Remplacer 'dev' par 'prod' ==="
sed 's/dev/prod/g' app.conf

echo ""
echo "=== Remplacer seulement dans les lignes de config (pas les commentaires) ==="
sed '/^#/!s/localhost/db.prod.internal/g' app.conf

echo ""
echo "=== Supprimer les lignes de commentaires ==="
sed '/^#/d' app.conf

echo ""
echo "=== Supprimer les lignes vides ==="
sed '/^$/d' app.conf

echo ""
echo "=== Insérer une ligne avant une ligne spécifique ==="
sed '/^log_level/i # Niveau de log (DEBUG, INFO, WARNING, ERROR)' app.conf

echo ""
echo "=== Transformation complète pour la production ==="
sed \
  -e 's/localhost/db.prod.internal/g' \
  -e 's/5432/5432/' \
  -e 's/myapp_dev/myapp_prod/' \
  -e 's/developer/app_user/' \
  -e 's/log_level=DEBUG/log_level=WARNING/' \
  -e 's|api_url=http://localhost:8080|api_url=https://api.monapp.com|' \
  -e 's/workers=2/workers=8/' \
  app.conf

Tâche 4 : Script d'analyse de logs complet

bash
cat > analyser-logs.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail

FICHIER_LOG="${1:-access.log}"
RAPPORT="${2:-/tmp/rapport-$(date +%Y%m%d).txt}"

[[ -f "$FICHIER_LOG" ]] || { echo "Fichier introuvable : $FICHIER_LOG" >&2; exit 1; }

{
  echo "RAPPORT D'ANALYSE - $(date '+%Y-%m-%d %H:%M:%S')"
  echo "Fichier : $FICHIER_LOG ($(wc -l < "$FICHIER_LOG") lignes)"
  echo "=============================================="

  echo ""
  echo "--- Résumé des codes HTTP ---"
  awk '{print $9}' "$FICHIER_LOG" | sort | uniq -c | sort -rn

  echo ""
  echo "--- Top 5 des URLs les plus consultées ---"
  awk '$9 == 200 {print $7}' "$FICHIER_LOG" | sort | uniq -c | sort -rn | head -5

  echo ""
  echo "--- Erreurs 5xx ---"
  awk '$9 >= 500 && $9 < 600 {print $1, $7, $9}' "$FICHIER_LOG" || echo "Aucune erreur 5xx"

  echo ""
  echo "--- IPs avec plus de 3 erreurs 4xx ---"
  awk '$9 >= 400 && $9 < 500 {err[$1]++} END {
    for (ip in err) if (err[ip] >= 3) print ip, err[ip]" erreurs"
  }' "$FICHIER_LOG" || echo "Aucune IP suspecte détectée"

} | tee "$RAPPORT"

echo ""
echo "Rapport sauvegardé : $RAPPORT"
EOF
chmod +x analyser-logs.sh
./analyser-logs.sh access.log

✅ Vérification du résultat

  • awk calcule la moyenne CPU depuis serveurs.csv
  • Les requêtes Python suspectes sont identifiées dans les logs
  • sed transforme app.conf pour la production
  • analyser-logs.sh génère un rapport dans /tmp/

💡 À retenir

OutilUsage principal
awkColonnes, calculs, agrégations, statistiques
sedSubstitutions, insertions, suppressions de lignes
grepFiltrage, recherche de patterns
Pipelinegrep | awk | sed | sort | uniq -c | sort -rn | head

awk en une phrase : pour chaque ligne ({}), avec des actions spéciales au début (BEGIN {}) et à la fin (END {}), accéder aux colonnes $1, $2... et au numéro de ligne NR.


✨ Solution Complète

bash
# Analyser des logs en une commande
# Top 5 IPs avec erreurs 4xx
awk '$9 >= 400 && $9 < 500 {err[$1]++} END {
  for (ip in err) print err[ip], ip
}' access.log | sort -rn | head -5

# Transformer une config de dev à prod
sed -e 's/localhost/prod-server/g' -e 's/DEBUG/INFO/g' app.conf > app.prod.conf
Retour au module

Sur cette page

  • 🎯 Objectifs
  • 📖 Contexte
  • 📋 Énoncé
  • 🧭 Déroulement de l'exercice
  • Tâche 1 : Fondamentaux awk
  • Tâche 2 : Analyse de logs Apache/Nginx
  • Tâche 3 : sed pour les transformations
  • Tâche 4 : Script d'analyse de logs complet
  • ✅ Vérification du résultat
  • 💡 À retenir
  • ✨ Solution Complète