Linux / Commande grep : rechercher du texte et filtrer les résultats
grep est une commande utilisée pour trouver les lignes correspondant à un motif spécifié dans des fichiers ou la sortie des commandes. Elle prend en charge non seulement les recherches de base, mais aussi l'ignorance de la casse, la sélection des lignes ne correspondant pas au motif, les recherches récursives dans les répertoires, les expressions régulières et l'affichage du contexte environnant.
Ce guide décrit GNU grep, l’implémentation courante des distributions Linux. Certaines options longues sont des extensions GNU ; d’autres implémentations peuvent utiliser des codes d’erreur supérieurs à 2.
La forme la plus basique est grep 'pattern' filename. Comme le motif peut contenir des caractères ayant des significations spéciales dans le shell, il est plus sûr de l'entourer habituellement de guillemets simples.
Qu'est-ce que la commande grep ?
grep lit l'entrée ligne par ligne et affiche les lignes qui correspondent au modèle. Le nom provient de l'expression de commande dans l'éditeur de texte Unix ed, g/re/p, ce qui signifie trouver et imprimer les lignes qui correspondent à une expression régulière sur l'ensemble de la plage.
Si vous ne spécifiez pas de fichier à rechercher, il lit depuis l'entrée standard, vous pouvez donc diriger la sortie d'une autre commande pour la rechercher. La syntaxe de modèle par défaut de GNU grep est l'Expression Régulière Basique (BRE), et utiliser -E permet l'utilisation de l'Expression Régulière Étendue (ERE).
Syntaxe de base et première recherche
La syntaxe de base est la suivante. Les crochets indiquent les éléments facultatifs, donc ne les saisissez pas dans la commande réelle.
grep [option] 'pattern' [file...]
Pour essayer les recherches sans toucher à vos journaux, ouvrez Bash avec GNU grep installé et créez ces fichiers dans un nouveau répertoire temporaire. Les commandes grep suivantes lisent les fichiers sans les modifier.
grep_start=$PWD
grep_demo=$(mktemp -d) || exit 1
cd "$grep_demo" || exit 1
printf '%s\n' 'INFO service ready' 'ERROR database timeout' 'WARN retry scheduled' 'ERROR ERROR request failed' 'DEBUG details' 'FATAL shutdown' > app.log
printf '%s\n' 'INFO worker started' 'ERROR worker stopped' > worker.log
printf '%s\n' 'ERROR' 'FATAL' > patterns.txt
Pour trouver des lignes contenant ERROR dans app.log, exécutez comme suit.
grep 'ERROR' app.log
Avec ce fichier d’exemple, la recherche affiche ERROR database timeout et ERROR ERROR request failed. Les résultats ne comportent pas de numéro tant que -n n’est pas utilisé.
Si vous spécifiez plusieurs fichiers, le nom du fichier apparaît avec chaque résultat.
grep 'ERROR' app.log worker.log
Les exemples ci-dessous supposent que les fichiers indiqués existent et sont lisibles. Adaptez les chemins à vos fichiers. L’accès à dmesg peut être restreint par la politique du système.
Vous pouvez également rechercher dans l'entrée standard. La commande suivante montre les lignes dans les messages du noyau contenant usb, sans tenir compte de la casse.
dmesg | grep -i 'usb'
Options grep fréquemment utilisées
| Option | Fonction | Exemples d'utilisation |
|---|---|---|
-i |
Recherche insensible à la casse | grep -i 'error' app.log |
-v |
Sélectionner les lignes qui ne correspondent pas | grep -v '^#' config |
-n |
Afficher les numéros de ligne dans le résultat | grep -n 'TODO' main.c |
-w |
Rechercher le motif comme un mot entier | grep -w 'cat' words.txt |
-x |
Sélectionner la ligne entière lorsqu'elle correspond au motif | grep -x 'enabled' status.txt |
-F |
Traiter le motif comme une chaîne fixe, et non comme une expression régulière | grep -F 'a.b' data.txt |
-E |
Utiliser des expressions régulières étendues | grep -E 'error|failed' app.log |
-r |
Rechercher récursivement dans les sous-répertoires | grep -r 'listen' /etc/nginx |
-l |
Imprimer uniquement les noms de fichiers correspondants | grep -rl 'deprecated' src |
-c |
Imprimer le nombre de lignes correspondantes par fichier | grep -c 'ERROR' app.log |
-A, -B, -C |
Imprimer le contexte après, avant ou autour des lignes correspondantes | grep -C 2 'panic' app.log |
Les options ci-dessus peuvent être combinées. Par exemple, grep -in 'error' app.log recherchera en ignorant la casse et affichera également les numéros de ligne. Le comportement détaillé et les options d'extension GNU peuvent être trouvés dans la documentation officielle de GNU Grep.
Faire la distinction entre les chaînes et les expressions régulières
Rechercher des chaînes fixes avec -F
Les caractères qui ont des significations particulières dans les expressions régulières, comme les points, les astérisques et les crochets, peuvent être recherchés littéralement en utilisant -F. Dans la commande suivante, le point est traité comme un véritable point plutôt que comme n'importe quel caractère.
grep -F '192.168.0.1' access.log
Si le terme de recherche est une simple chaîne, vous pouvez réduire les échappements inutiles et clarifier votre intention.
Utilisez des expressions régulières étendues avec -E
L'utilisation de -E vous permet d'utiliser la syntaxe des expressions régulières étendues, comme |, +, ?, et les parenthèses, de manière plus lisible. L'exemple suivant trouve les lignes qui contiennent l'un de ERROR, WARN ou FATAL.
grep -E 'ERROR|WARN|FATAL' app.log
Dans GNU grep, la différence entre les expressions régulières de base et les expressions régulières étendues réside principalement dans la notation. Si la compatibilité avec d'autres environnements est importante, vérifiez l'implémentation grep du système cible et les options prises en charge.
Spécifier le début et la fin d'une ligne
Le caret (^) représente le début d'une ligne, et le signe dollar ($) représente la fin d'une ligne. Une ligne vide peut être trouvée avec ^$, qui n'a aucun caractère entre le début et la fin.
grep '^server' config.txt
grep 'completed$' job.log
grep '^$' notes.txt
Pour exclure les lignes vides et les lignes de commentaire d'un fichier de configuration, vous pouvez appliquer les deux conditions dans l'ordre comme suit.
grep -v '^[[:space:]]*#' app.conf | grep -v '^[[:space:]]*$'
Réduire la plage de recherche avec précision
Faire correspondre des mots entiers et des lignes entières
-w sélectionne les correspondances délimitées par les bords de ligne ou des caractères autres que les lettres, chiffres et traits de soulignement. Les limites dépendent aussi de la locale. Par exemple, grep -w 'cat' trouvera cat mais ne sélectionnera pas cat au sein de category.
grep -w 'root' /etc/passwd
-x sélectionne une ligne seulement lorsque toute la ligne correspond exactement au motif.
grep -x 'active' service-status.txt
Trouver les lignes ne correspondant pas
-v inverse la sélection. L'exemple suivant n'affiche que les lignes qui ne contiennent pas DEBUG.
grep -v 'DEBUG' app.log
Lorsqu'il est combiné avec -i, vous pouvez exclure sans tenir compte de la casse.
grep -iv 'debug' app.log
Recherche de plusieurs motifs à la fois
Utiliser -e plusieurs fois vous permet de spécifier chaque motif séparément. Vous n'avez pas à les combiner en une seule expression régulière complexe, ce qui facilite la lecture dans les scripts.
grep -e 'ERROR' -e 'FATAL' app.log
S'il y a de nombreux motifs, vous pouvez créer un fichier avec un motif par ligne et le lire avec -f.
grep -f patterns.txt app.log
Recherche récursive dans l’ensemble des répertoires
Différence entre -r et -R
-r recherche récursivement les fichiers sous le répertoire spécifié. Il suit les liens symboliques spécifiés directement sur la ligne de commande, mais ignore les liens symboliques rencontrés lors des recherches récursives.
grep -rn 'database_url' ./config
Le -R de GNU grep suit les liens symboliques rencontrés lors des recherches récursives. Le périmètre peut dépasser le répertoire prévu ; GNU grep peut aussi signaler une boucle de répertoires. Ainsi, utilisez-le lorsque l'intention est claire.
Inclusion et exclusion des types de fichiers
--include recherche uniquement les modèles de noms de fichiers spécifiés, et --exclude ignore les fichiers correspondants. Mettez les modèles entre guillemets afin que le shell n'étende pas d'abord les astérisques.
grep -rn --include='*.conf' 'timeout' /etc
grep -rn --exclude='*.min.js' 'deprecated' ./src
Pour exclure des répertoires spécifiques, utilisez --exclude-dir.
grep -rn --exclude-dir='.git' --exclude-dir='node_modules' 'api_key' .
Vérifiez uniquement les noms de fichiers correspondants
Si vous avez besoin d'une liste de fichiers plutôt que du contenu correspondant, utilisez -l. Chaque fichier cesse d'être recherché après la première correspondance trouvée, ce qui convient également bien à l'objectif.
grep -rl --include='*.html' 'jb-heading' .
Inversement, pour trouver uniquement des fichiers sans modèles correspondants, utilisez le -L en majuscules.
grep -rL --include='*.html' 'jb-heading' .
Présentez les résultats dans un format lisible
Affichez les numéros de ligne et les noms de fichiers
-n affiche les numéros de ligne des lignes correspondantes. Même en recherchant dans un seul fichier, pour forcer l'affichage du nom du fichier, utilisez -H de GNU grep, et pour masquer le nom du fichier, utilisez -h.
grep -nH 'listen' nginx.conf
Afficher le contexte avant et après les lignes correspondantes
S’il est difficile de déterminer la cause à partir des lignes d'erreur uniquement, utilisez -A, -B ou -C pour voir les lignes environnantes. Le chiffre indique combien de lignes supplémentaires sont imprimées.
grep -A 3 'ERROR' app.log
grep -B 2 'ERROR' app.log
grep -C 2 'ERROR' app.log
-A 3 ajoute 3 lignes après, -B 2 ajoute 2 lignes avant, et -C 2 ajoute 2 lignes avant et après.
Impression uniquement de la partie correspondante
-o affiche uniquement les portions non vides qui correspondent au motif, chacune sur sa propre ligne. S'il y a plusieurs correspondances sur une même ligne, chaque correspondance est imprimée séparément.
grep -oE '[0-9]{3}-[0-9]{4}' contacts.txt
Pour mettre en évidence les correspondances dans le terminal, vous pouvez utiliser --color=auto. Lors du passage de la sortie vers un fichier ou une autre commande, utilisez auto ou never pour éviter que les caractères de contrôle de couleur ne se mélangent.
Utilisation dans les journaux et les sorties de commande
Trouver des erreurs dans les journaux récents
Pour rechercher uniquement dans la plage récente au lieu de tout le journal, connectez-le avec tail.
tail -n 500 app.log | grep -iE 'error|failed|fatal'
Si vous souhaitez filtrer en continu les nouveaux journaux ajoutés au fichier, vous pouvez l'utiliser comme suit.
tail -n 0 -F app.log | grep --line-buffered 'ERROR'
--line-buffered est une option d'extension GNU qui vide le tampon de sortie à mesure que chaque ligne arrive, réduisant ainsi les délais dans le pipeline. Des méthodes pour le suivi, y compris la rotation des journaux, peuvent être trouvées sur le guide de la commande tail.
Filtrage des résultats des services et des processus
Vous pouvez rechercher un nom de service spécifique dans la sortie de systemctl.
systemctl list-unit-files | grep 'nginx'
Si votre objectif est seulement de vérifier l'existence d'un processus, pgrep est souvent plus direct que ps | grep. Pour rechercher avec le nom de la commande et ses arguments ensemble, vous pouvez l'exécuter comme suit.
pgrep -af 'nginx'
Comptage des lignes correspondantes
-c affiche le nombre de lignes correspondantes, et non le nombre de correspondances. Même si une ligne contient le motif plusieurs fois, cette ligne n'est comptée qu'une seule fois.
grep -c 'ERROR' app.log
Pour compter les occurrences non vides et sans chevauchement dans le fichier, vous pouvez séparer chaque correspondance avec -o puis compter avec wc -l.
grep -o 'ERROR' app.log | wc -l
Dans le fichier d’exemple, grep -c affiche 2, tandis que le pipeline avec -o et wc -l affiche 3 : une ligne contient deux occurrences de ERROR.
Vérifier l'existence sans sortie
-q n'affiche pas les résultats et ne renvoie qu'un statut de sortie. Il est adapté pour vérifier l'existence d'un motif dans une condition shell.
if grep -q 'ready' status.log; then
echo 'Service ready'
fi
Comprendre le statut de sortie de grep
grep communique les résultats de recherche non seulement via la chaîne de sortie mais aussi via le statut de sortie. En général, il renvoie 0 s'il y a des lignes correspondantes, 1 s'il n'y a pas de lignes correspondantes, et 2 s'il ne peut pas lire un fichier ou s'il y a un problème de syntaxe.
| Statut de sortie | Signification | Décision dans les scripts |
|---|---|---|
0 |
Une ou plusieurs correspondances trouvées | Traitez comme si la condition était vraie |
1 |
Aucune correspondance trouvée | Pourrait être un résultat de recherche normal |
2 |
Une erreur s'est produite | Vérifiez le fichier d'entrée, les autorisations ou le motif |
Par conséquent, vous ne devez pas conclure que l'exécution de la commande elle-même a échoué simplement parce qu'il n'y a pas de résultats. Dans l'automatisation, vous devez distinguer entre 1 et une véritable erreur 2. GNU grep -q peut se terminer avec le statut 0 si une correspondance est trouvée, même s'il y a d'autres erreurs, donc si la détection des erreurs dans tous les fichiers d'entrée est importante, une vérification séparée est nécessaire.
Problèmes courants et solutions
Lorsque le motif commence par un tiret
Les motifs -ERROR comme celui-ci peuvent être confondus avec des options. Mettez le motif après --, qui indique la fin des options.
grep -- '-ERROR' app.log
Lorsque le message 'Fichier binaire correspond' apparaît
Si GNU grep détermine que l'entrée est un fichier binaire, il peut afficher le message au lieu des lignes correspondantes. Si vous êtes sûr qu'il s'agit réellement d'un fichier texte, vous pouvez le traiter comme texte en utilisant -a.
grep -a 'ERROR' mixed-data.log
Inversement, pour exclure les fichiers binaires lors de recherches récursives, vous pouvez utiliser -I. N'utilisez pas toujours -a sur des données binaires inconnues, car elles peuvent contenir des caractères de contrôle qui peuvent perturber votre terminal.
Lorsque les résultats diffèrent en raison des caractères spéciaux des regex
Le point correspond à n'importe quel caractère unique et l'astérisque signifie la répétition de l'expression précédente dans les expressions régulières. Si vous souhaitez rechercher une chaîne simple, utilisez -F, et si vous souhaitez utiliser une expression régulière, encadrez l'ensemble du motif entre des guillemets simples pour éviter l'expansion du shell.
Lorsque les recherches récursives sont trop lentes ou produisent trop de résultats
Réduisez le répertoire de départ pour la recherche et excluez les fichiers inutiles en utilisant --include, --exclude, et --exclude-dir. Pour masquer uniquement les erreurs de permission, vous pourriez être tenté de supprimer toutes les erreurs standard, mais cela peut vous faire manquer des problèmes importants. Il est donc préférable de vérifier d'abord la portée de la recherche et les permissions des fichiers.
Questions fréquemment posées
Grep distingue-t-il par défaut les lettres majuscules des lettres minuscules ?
Oui. La recherche par défaut est sensible à la casse. Pour ignorer la casse, utilisez -i. Vous devez également considérer que les résultats du traitement de la casse peuvent varier en fonction de la locale.
Quelle est la différence entre grep -r et grep -R ?
Dans GNU grep, les deux effectuent des recherches récursives, mais -R suit tous les liens symboliques rencontrés lors de la recherche. Pour les recherches de code source ou de fichiers de configuration habituelles, -r est plus facile à prévoir.
Est-ce une erreur si aucun résultat de recherche n'est trouvé ?
Pas nécessairement. S'il n'y a pas de correspondances, il renvoie généralement un statut de sortie 1, tandis que les erreurs comme l'échec d'accès au fichier ou les options invalides sont distinguées par le statut 2.
Comment puis-je trouver des lignes qui contiennent au moins un de plusieurs termes de recherche ?
grep -E 'error|warning' filename utilise l'opérateur d'alternance dans les expressions régulières étendues, ou vous pouvez répéter -e comme grep -e 'error' -e 'warning' filename. Pour traiter le terme de recherche comme une chaîne simple plutôt qu'une expression régulière, vous pouvez également utiliser -F.
Après les essais, revenez au répertoire initial avec cd "$grep_start". Le chemin du dossier d’essai est conservé dans grep_demo : vous pouvez supprimer ses trois fichiers puis le dossier après avoir vérifié ce chemin.
Résumé
Pour les recherches de chaînes générales, il est bon de se familiariser avec grep -F ; pour plusieurs conditions d'expressions régulières, grep -E ; et pour rechercher dans un répertoire entier, grep -r. Pour rendre les résultats plus faciles à interpréter, vous pouvez utiliser -n et -C ; si vous avez seulement besoin de la liste des fichiers, utilisez -l ; et pour vérifier l'existence dans les scripts, utilisez -q.
Encadrez les motifs par des guillemets simples, limitez spécifiquement la portée des recherches récursives, et distinguez entre le statut de sortie 1 et le statut d'erreur 2 — ce sont des éléments clés pour une utilisation sûre.




