Filtrer des lignes selon un motif, sans ligne de commande
Publié le 07/08/2026 · 12 min de lecture · Outils texte & langage
Daniel Okonkwo — Développeur front-end et rédacteur Tech chez OneKitly
Performance web · Formats de fichiers
Vérifié à partir de 3 sources
filter-lines découpe ton texte sur les sauts de ligne, teste la présence d'une sous-chaîne dans chaque ligne, et la garde ou l'écarte. La comparaison est un includes de chaîne sur un terme littéral — il n'y a aucun moteur d'expressions régulières derrière la zone de saisie. Taper ^ERROR dans un journal n'a rien rendu ; ERROR|WARN non plus ; [a-z]+ non plus. Chacun a produit un panneau de sortie vide, sans message d'erreur et sans indication que le motif avait été lu littéralement : c'est le comportement à connaître avant de commencer. L'inverse est vrai aussi et plus rassurant : une expression régulière invalide est inoffensive ici, puisque ce n'est pas une expression régulière. Taper une simple parenthèse ouvrante a bien retenu la ligne qui en contient une, exactement comme souhaité. « Ignorer la casse » est actif par défaut : filtrer sur « apple » a gardé la ligne « APPLE juice » aussi bien que « apple pie » ; grep dans un terminal respecte la casse par défaut, cet outil non, différence à garder en tête si tu es habitué à l'un des deux. L'action propose « Garder les lignes correspondantes » et « Supprimer les lignes correspondantes », qui correspondent à grep et grep -v. Laisser le terme vide rend ton texte inchangé, et non rien. Deux détails issus des essais : le mode « supprimer » conserve les lignes vides, car une ligne vide ne contient pas ton terme, donc un journal filtré revient avec les trous laissés par les lignes retirées ; et toute la sortie est rejointe par de simples sauts de ligne, si bien qu'un fichier Windows perd ses retours chariot au passage.
C'est grep pour ceux qui n'utilisent pas grep, avec une différence de taille : la recherche est une sous-chaîne littérale, si bien qu'une vraie expression régulière renvoie une zone vide sans message d'erreur. Chaque affirmation a été vérifiée en exécutant l'outil.
Ce que fait grep, et quelle moitié se trouve ici
grep lit un texte ligne par ligne, confronte chaque ligne à un motif, et écrit les lignes qui correspondent. La spécification POSIX le définit ainsi et définit le motif comme une expression régulière — un petit langage où un accent circonflexe signifie « début de ligne », une barre verticale « ou bien », des crochets « l'un quelconque de ces caractères » et un plus « une ou plusieurs fois ce qui précède ». L'option d'inversion retourne le test et affiche les lignes qui ne correspondent pas. L'idée a une quarantaine d'années et reste le moyen le plus rapide de répondre à une question sur un fichier journal.
filter-lines implémente la boucle et l'option d'inversion, et s'arrête là. Le langage de motifs n'est pas implémenté, et surtout il ne l'est pas à moitié : le terme que tu tapes est comparé comme une suite de caractères, entière et inchangée. C'est une conception légitime pour une zone de saisie sur une page web — la plupart des gens qui filtrent une liste veulent les lignes contenant le mot « facture », pas une grammaire — mais cela signifie que les deux outils prennent la même entrée et donnent des réponses différentes, et celui qui se trompe ne le dit jamais.
La zone vide, et pourquoi elle est vide
Trois motifs ont été passés sur le même journal de sept lignes. ^ERROR n'a rien rendu, alors que deux lignes commencent par ERROR, parce qu'aucune ligne ne contient un accent circonflexe littéral suivi des lettres E, R, R, O, R. ERROR|WARN n'a rien rendu, alors que le journal contient un de chaque, parce qu'aucune ligne ne contient une barre verticale littérale entre ces deux mots. [a-z]+ n'a rien rendu, pour la même raison : aucune ligne ne contient de crochet. Dans chaque cas, le panneau de sortie était simplement vide. Rien n'était mis en évidence, rien n'était signalé, et rien ne laissait entendre que le terme avait été lu autrement que voulu.
C'est le mode de défaillance qui compte, et c'est l'inverse de ce que l'expression « regex invalide » suggérerait. Un motif malformé est le cas sûr. Taper une simple parenthèse ouvrante — ce qui ferait lever à un moteur d'expressions régulières une erreur de groupe non terminé — a retenu la ligne contenant une parenthèse et l'a rendue. De même pour un point isolé, qui dans le langage des expressions régulières signifie « n'importe quel caractère » et qui ici signifie « un point » : sur une liste contenant a.b et aXb, il n'a rendu que a.b. Si tu te surprends à taper de la syntaxe d'expression régulière dans cette zone, le réflexe à construire est de regarder la sortie et de te demander si un résultat vide est plausible, car l'outil ne se posera pas la question à ta place.
Casse, accents et l'espace que tu n'as pas voulu taper
« Ignorer la casse » est actif d'emblée, et met en minuscules la ligne comme le terme avant de comparer. Filtrer une liste de cinq fruits sur « apple » a gardé « apple pie », « APPLE juice » et « pineapple tart » ; désactiver la bascule a écarté « APPLE juice » et gardé les deux autres. La ligne « pineapple » rappelle qu'il s'agit d'un test de sous-chaîne et non de mot : « apple » est contenu dans « pineapple », la ligne correspond donc, et aucune option « mot entier » ne vient l'en empêcher. S'il te faut des limites de mot, ajoute les espaces autour de ton terme et accepte de rater le mot en début ou en fin de ligne.
Deux pièges plus petits sont sortis des mêmes essais. Une espace en tête du terme fait partie du terme : filtrer la même liste sur « espace + apple » n'a rien rendu, parce qu'aucune ligne n'a d'espace devant ce mot à la position testée. Et les accents suivent la règle de l'article sur les doublons : un terme dont la lettre accentuée s'écrit comme une lettre plus un signe combinant n'a rien trouvé dans une liste dont la lettre accentuée est un point de code unique, alors que les deux paraissent identiques dans le champ de recherche. Les deux reviennent à la même discipline : ce que tu as tapé est comparé exactement tel que tapé, y compris les parties que tu ne vois pas.
Le mode « supprimer » laisse des trous
Bascule l'action sur « Supprimer les lignes correspondantes » et l'outil écarte chaque ligne contenant ton terme et garde tout le reste — y compris les lignes vides, car une ligne vide ne contient pas ton terme. Passe-le sur un journal comportant une ligne vide entre deux entrées et la ligne vide est encore là ensuite. Ce n'est pas un bogue, c'est la lecture honnête de la consigne, mais le résultat ressemble rarement à ce qu'on attendait, et un fichier filtré parsemé d'une douzaine de trous orphelins est pénible à lire. Le remède tient en une étape de plus : passe remove-blank-lines sur la sortie.
Un dernier comportement sur lequel s'appuyer : un terme vide rend ton texte inchangé, et non un résultat vide. Cela paraît évident, mais la lecture inverse — pas de terme, donc rien ne correspond, donc rien ne sort — serait tout aussi défendable et viderait silencieusement ton entrée chaque fois que tu effaces le champ pour taper une nouvelle recherche. L'outil prend la branche la plus sûre, et cela a été vérifié : le champ vide, les cinq lignes de la liste d'essai sont revenues.
Que faire quand il te faut vraiment un motif
La plupart des questions de motif se réécrivent en questions de sous-chaîne. « Les lignes qui commencent par un code » devient « les lignes qui contiennent ce code », ce qui est plus lâche mais convient généralement sur un journal où le code n'apparaît de toute façon qu'au début. « L'un ou l'autre de deux mots » devient deux passes — filtre sur le premier, note le résultat, filtre l'original sur le second — puisqu'il n'y a pas d'alternative. « Une plage de caractères » devient en général plusieurs passes, ou un autre outil. Quand la réponse exige vraiment une grammaire, le conseil honnête est qu'une zone de texte dans un navigateur est le mauvais instrument, et que le bon est un terminal ou un éditeur de texte doté d'une recherche par expression régulière.
Une réserve sur l'outil frère. find-and-replace, sur ce même site, prend lui aussi un terme littéral : il échappe chaque caractère à sens spécial avant de construire son motif, ce qui a été lu dans sa source et confirmé. Si tu espérais t'en servir pour simuler un filtre par expression régulière, ce n'est donc pas possible. Les deux outils sont cohérents entre eux, c'est la bonne nouvelle ; aucun des deux n'est grep, c'est la nouvelle qu'il te fallait avant de commencer.
| Terme tapé | Ce qui revient | Pourquoi |
|---|---|---|
| apple, « Ignorer la casse » actif (par défaut) | apple pie, APPLE juice et pineapple tart | Les deux côtés sont mis en minuscules, et le test porte sur la sous-chaîne, pas le mot entier |
| apple, « Ignorer la casse » désactivé | apple pie et pineapple tart seulement | APPLE juice ne contient plus les caractères exacts tapés |
| ^ERROR sur un journal dont les deux premières lignes commencent par ERROR | Sortie vide, aucun message d'erreur | Aucune ligne ne contient un accent circonflexe littéral suivi de ces cinq lettres |
| ERROR|WARN sur le même journal | Sortie vide | Il n'y a pas d'alternative ; la barre verticale n'est qu'un caractère à chercher |
| Une simple parenthèse ouvrante | La ligne qui contient une parenthèse — cela fonctionne | Une expression régulière invalide est le cas sûr, puisque aucune n'est compilée |
| Un point isolé, sur une liste contenant a.b et aXb | a.b seulement | Le point correspond à un point, pas à n'importe quel caractère |
| Un champ « Contient » vide | Le texte entier, inchangé | L'outil sort tout de suite plutôt que de tout filtrer |
| N'importe quel terme, en mode « Supprimer les lignes correspondantes », sur un texte avec des lignes vides | Les lignes vides survivent | Une ligne vide ne contient pas le terme : ce n'est pas une correspondance à supprimer |
Questions fréquentes
- Puis-je utiliser une expression régulière dans le champ « Contient » ?
- Non. Le terme est comparé littéralement, caractère par caractère, sans aucun langage de motifs derrière. Cela a été vérifié sur trois motifs ordinaires — une ancre de début de ligne, une alternative et une classe de caractères — et les trois ont rendu un panneau de sortie vide sans message. Le comportement à intérioriser est qu'une mauvaise réponse ressemble ici exactement à une réponse correcte « rien ne correspond » : traite donc un résultat vide comme une question et non comme un fait, retape le terme sans ses caractères de syntaxe et regarde si des lignes apparaissent.
- Comment ne garder que les lignes qui commencent par quelque chose ?
- Tu ne peux pas demander « début de ligne » ici, faute d'ancre. En pratique la version sous-chaîne suffit généralement : filtre sur le code ou le préfixe lui-même, et accepte les lignes qui le contiennent ailleurs. Que ce soit acceptable dépend de tes données, et tu peux le savoir à peu de frais — filtre une fois, puis passe le même terme en mode « supprimer » et regarde ce qui sort. Si le tas supprimé ne contient rien que tu voulais, la version large convenait. S'il te faut vraiment l'ancre, un éditeur de texte avec recherche par expression régulière est l'outil adapté.
- Le filtre respecte-t-il la casse ?
- Pas par défaut. « Ignorer la casse » est actif au chargement de la page, à l'inverse du réglage par défaut de grep et à l'inverse de ce qu'attend un habitué du terminal. Désactive-le dans le même panneau si la distinction t'importe — filtrer une liste de fruits sur « apple » avec la bascule active a gardé une ligne « APPLE juice », et la désactiver a écarté cette ligne tout en gardant les deux en minuscules. Le repliement est le repliement simple, indépendant de la langue : il traite correctement les majuscules accentuées mais ne fait rien de particulier pour une langue donnée.
- Pourquoi ma sortie filtrée est-elle trouée ?
- Parce que tu as utilisé « Supprimer les lignes correspondantes » et que ton texte contenait des lignes vides. Une ligne vide ne contient pas ton terme, l'outil la garde donc, et elle reste exactement là où elle était — désormais entourée de l'espace qu'occupaient les lignes retirées. Passer remove-blank-lines sur le résultat les referme toutes d'un coup. Si tu enchaînes plusieurs filtres, fais le nettoyage des lignes vides une seule fois à la fin plutôt qu'après chaque étape, car chaque passe « supprimer » ouvrira de nouveaux trous.
- L'outil m'indique-t-il combien de lignes correspondent ?
- Aucun compte n'est affiché ; tu obtiens les lignes correspondantes et rien d'autre. Si tu as besoin du nombre, le chemin le plus court est de passer le résultat dans un compteur de lignes, ou d'utiliser count-occurrences sur le texte d'origine avec le même terme — en gardant en tête qu'il compte les occurrences et qu'une même ligne peut contenir ton terme deux fois, si bien que les deux nombres peuvent légitimement différer. Si c'est le compte qui t'intéresse et non les lignes, count-occurrences est le meilleur point de départ.
Articles qui pourraient t'intéresser
Tous les guides →Outils similaires
Tout ce qui suit décrit ce que font ces outils aujourd'hui, vérifié en exécutant leurs propres transformations sur les entrées exactes reproduites dans chaque article, et non ce qu'une norme imposerait à un outil de texte. Le traitement du texte ligne à ligne n'a aucune autorité unique : ce qui compte comme espace, le fait que deux lignes accentuées soient ou non la même ligne, et l'endroit où se termine une URL dans une phrase sont tranchés différemment par chaque programme dans lequel tu colleras du texte. Quand un outil se trompe sur un cas, c'est dit franchement plutôt que contourné. Avant de passer tout cela sur une liste que tu ne pourras pas réexporter, passe sur une copie et compare le nombre de lignes aux deux bouts.
Sources
Tu as repéré une erreur dans cet article ?