15/11/2024

PowerShell

PowerShell grep : rechercher des chaînes de caractères avec Select-String

I. Présentation

Dans ce tutoriel, nous allons voir comment utiliser grep en PowerShell grâce à la commande Select-String dans le but de rechercher une chaîne de caractères dans un ensemble de fichiers.

La commande "grep" est très populaire sous Linux et elle est très appréciée des administrateurs système. En effet, elle permet de rechercher des chaînes de caractères au sein de fichiers présents sur votre machine, de manière efficace. Au quotidien, c'est très pratique pour rechercher un mot clé dans un fichier de configuration ou effectuer une recherche au sein d'un fichier de log.

Sous Windows, il existe une commande équivalente à grep par l'intermédiaire de PowerShell. Il s'agit de la commande Select-String et je vous propose d'apprendre à l'utiliser en lisant cet article. Il y a également une autre alternative sous Windows, par l'intermédiaire de l'outil natif findstr.exe.

II. Les paramètres de Select-String

La commande Select-String contient de nombreux paramètres qui vont être utiles pour affiner notre filtre de recherche. Avant de passer à la pratique, il me semblait intéressant de vous lister et de vous expliquer les paramètres principaux.

-AllMatches

Rechercher toutes les occurrences de notre chaîne de caractères / de notre filtre sur une même ligne. Par défaut, Select-String va s'arrêter dès qu'il trouvera un premier résultat sur une ligne, ce qui peut s'avérer contraignant. Avec ce paramètre, nous aurons tous les résultats, sans limites. Autrement dit, sans -AllMatches, on peut avoir seulement un résultat par ligne.

-CaseSensitive

Par défaut, la recherche n'est pas sensible à la casse. Lorsque ce paramètre est défini, la recherche va tenir compte de la casse, c'est-à-dire des minuscules et majuscules.

-Context

Paramètre très intéressant qui va permettre d'indiquer combien de lignes avant et après le match (résultat) il faut afficher, en plus de la ligne correspondante à la recherche. Je trouve cela particulièrement intéressant lorsque l'on s'intéresse à des logs.

-Encoding

Permets de spécifier l'encodage à utiliser. Par défaut "utf8NoBOM", mais il y a d'autres choix : ascii, oem, unicode, utf8, utf32, etc.

-Exclude

Exclure certains fichiers du périmètre de la recherche. Par exemple, tous les fichiers qui utilisent une extension spécifique.

-Include

Inclure uniquement les fichiers correspondants au filtre -Inclure. Par exemple, pour effectuer une recherche uniquement sur les fichiers .log.

-InputObject

Rechercher dans un objet existant (envoyé en entrée) plutôt qu'au sein des fichiers stockés dans un dossier.

-NotMatch

Afficher les résultats qui ne correspondent pas au filtre de recherche / recherche inverse.

-Pattern

C'est ici que l'on spécifie le filtre de la recherche, ce qui peut être une simple chaîne de caractères, plusieurs chaînes de caractères, mais aussi un filtre sous la forme d'une expression régulière (regex).

-Path

Ce paramètre basique sert à spécifier le répertoire dans lequel effectuer la recherche ou le fichier dans lequel rechercher.

Maintenant que le décor est planté, passons à la pratique : connaître les paramètres de Select-String c'est bien, savoir les utiliser c'est encore mieux.

III. PowerShell grep avec Select-String : exemples

Pour mieux comprendre le fonctionnement de la commande "grep" à la sauce Windows, je vous propose quelques exemples.

A. PowerShell - Rechercher une chaîne de caractères dans un fichier

Commençons par rechercher une chaîne de caractères simple dans un fichier spécifique : la chaîne "florian" dans le fichier "data.csv" qui contient une liste d'utilisateurs.

Voici le contenu du fichier :

prenom;nom;
florian;burnel;
gerard;mensoif;
vincent;tyme;
maude;zarella;

Voici la commande recherche :

Select-String -Path "C:\TEMP\GREP\Data.csv" -Pattern "florian"

Voici le résultat :

Exemple d'utilisation de Select-String (grep) en PowerShell

Le résultat est correct puisqu'il a trouvé la ligne avec la chaîne "florian". Le terme est surligné dans le résultat pour bien montrer son emplacement dans la liste. Plus précisément, voici comment se décompose la ligne :

TEMP\GREP\Data.csv:2:florian;burnel;
<fichier-où-se-situe-le-résultat>:<numéro de ligne>:<contenu de la ligne>

Il y a plusieurs propriétés associées à cette commande. Par exemple, nous pouvons récupérer le numéro de la ligne :

(Select-String -Path "C:\TEMP\GREP\Data.csv" -Pattern "florian").LineNumber

Pour visualiser toutes les propriétés et méthodes disponibles, on utilisera "Get-Member" (gm).

Select-String -Path "C:\TEMP\GREP\Data.csv" -Pattern "florian" | gm

B. PowerShell - Rechercher une chaîne de caractères dans plusieurs fichiers

Nous pouvons rechercher la chaîne "florian" dans plusieurs fichiers, et pas seulement dans le fichier "data.csv". Si l'on veut rechercher ce terme dans tous les fichiers du dossier "C:\TEMP\GREP", on utilisera cette commande :

Select-String -Path "C:\TEMP\GREP\*" -Pattern "florian"

Voici le résultat :

TEMP\GREP\Data.csv:2:florian;burnel;
TEMP\GREP\Data3.csv:4:florian;burnel;

Cette fois-ci, la commande a trouvé deux résultats différents, au sein de deux fichiers distincts.

C. PowerShell - Rechercher plusieurs chaînes de caractères

Si l'on veut rechercher plusieurs chaînes de caractères différentes, il n'est pas nécessaire d'utiliser plusieurs commandes : le paramètre -Pattern prend en charge les valeurs multiples. Il suffit de les séparer par une virgule.

Voici un exemple :

Select-String -Path "C:\TEMP\GREP\*" -Pattern "florian","tyme"

Voici le résultat :

Lorsque l'on commence à rechercher plusieurs chaînes dans plusieurs fichiers, il me semble pertinent de revoir un petit peu la mise en forme du résultat. Pour cela, nous allons nous aider du cmdlet Select-Object pour sélectionner les propriétés que l'on souhaite afficher.

Par exemple, on peut récupérer le nom du fichier, le pattern trouvé et le contenu de la ligne :

Select-String -Path "C:\TEMP\GREP\*" -Pattern "florian","tyme" | Select-Object FileName, Pattern, Line

Ce qui donne :

Note : on pourrait remplacer "Filename" par "Path" pour afficher le chemin complet vers le fichier.

Pratique, n'est-ce pas ? 🙂

Pour affiner la recherche et sélectionner uniquement les fichiers TXT, il y a deux manières de procéder.

Note : au préalable, je fais une copie du fichier data.csv en data10.txt pour que cela fonctionne.

Tout d'abord, on peut indiquer le filtre directement au niveau de -Path, comme ceci :

Select-String -Path "C:\TEMP\GREP\*.txt" -Pattern "florian","tyme"

Sinon, on peut utiliser le paramètre -Include pour filtrer sur une extension de fichiers. Ce qui donne la commande suivante pour un filtre sur .TXT :

Select-String -Path "C:\TEMP\GREP\*" -Include "*.txt" -Pattern "florian","tyme"

L'avantage de -Include, c'est que l'on peut préciser plusieurs filtres. Voici un exemple pour .TXT et .CSV :

Select-String -Path "C:\TEMP\GREP\*" -Include "*.txt","*.csv" -Pattern "florian","tyme"

D. PowerShell - Rechercher à l'aide du paramètre -Context de Select-String

Le paramètre -Context permet d'afficher la ligne où le pattern a été trouvé, ainsi que les X lignes précédentes et les X lignes suivantes. Si l'on utilise -Context 3, on va obtenir 7 lignes au total : 3 lignes avant la ligne où le pattern est présent, la ligne où le pattern est présent, et 3 lignes après la ligne où le pattern est présent.

Voici un exemple où je recherche les erreurs 404 au sein d'un fichier de log de Nginx :

Select-String -Path "C:\TEMP\GREP\access-light.log" -Pattern "404" -Context 3

On peut gérer de façon indépendante le nombre de lignes avant et après à afficher. Il suffit de préciser deux valeurs séparées par une virgule. La première valeur correspond au nombre de lignes avant et la seconde au nombre de lignes après.

Par exemple, pour afficher une ligne avant et trois lignes après, cela donne :

Select-String -Path "C:\TEMP\GREP\access-light.log" -Pattern "404" -Context 1,3
Exemple d'utilisation de Select-String (grep) en PowerShell avec le paramètre -Context

Grâce au caractère ">" on peut repérer facilement la ligne où a été trouvé le pattern.

Sur un fichier très conséquent, la sortie dans la console peut être importante. On peut exporter le résultat de la recherche vers un autre fichier, comme ceci (vers le fichier C:\TEMP\resultat-grep.txt) :

Select-String -Path "C:\TEMP\GREP\access-light.log" -Pattern "404" -Context 1,3 | Out-File -Path "C:\TEMP\resultat-grep.txt"

On pourrait aussi limiter l'affichage au premier résultat ou au X premiers résultats. Pour cela, on va coupler Select-String à l'utilisation de Select-Object :

Select-String -Path "C:\TEMP\GREP\access-light.log" -Pattern "404" -Context 0,1 | Select-Object -First 1

On peut aussi affiner avec Select-Object et exporter dans un fichier ce résultat affiné :

Select-String -Path "C:\TEMP\GREP\access-light.log" -Pattern "404" -Context 1,3 | Select-Object -First 1 | Out-File -Path "C:\TEMP\resultat-grep.txt"

E. PowerShell - Recherche récursive avec Select-String

Seule, la commande Select-String recherche uniquement dans le dossier courant, mais pas de manière récursive c'est-à-dire que les sous-dossiers ne sont pas pris en compte. Pour utiliser la récursivité, il faut s'appuyer sur la commande Get-ChildItem puisqu'elle va permettre de récupérer la liste de l'intégralité des fichiers et dossiers. Ce résultat sera envoyé à la commande Select-String via le pipe "|". À partir de là, on peut effectuer un grep récursif à l'aide de PowerShell.

On viendra positionner le répertoire -Path au niveau de Get-ChildItem donc il n'est plus nécessaire de le spécifier au sein de Select-String.

Get-ChildItem -Path "C:\Temp\GREP\" -Recurse | Select-String -Pattern "florian"

Puisque ls et dir sont des alias de Get-ChildItem, on peut les utiliser également.

ls "C:\Temp\GREP\" -Recurse | Select-String -Pattern "florian"
dir "C:\Temp\GREP\" -Recurse | Select-String -Pattern "florian"

On peut voir sur l'image ci-dessous que nous avons un nouveau résultat, au sein du sous-dossier "SOUS-DOSSIER", ce qui n'était pas le cas précédemment.

PowerShell : comment utiliser Select-String de manière récursive ?

F. PowerShell - Rechercher toutes les adresses IP dans un fichier

Pour finir, je vous propose un dernier exemple où l'on va rechercher les adresses IP dans un fichier. Nous n'allons pas rechercher une adresse IP précise, car c'est trop facile, mais l'on va rechercher toutes les adresses IP présentes dans le fichier de log "access.log".

Pour cela, on va s'appuyer sur une expression régulière. Comme je l'expliquais dans mon tutoriel sur le sujet, on peut rechercher une adresse IP avec le pattern suivant :

\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}

Bien qu'il ne soit pas ultra précis, car il autorise les adresses IP 300.300.300.300, 400.500.600.700, etc... Il devrait être suffisant pour s'attaquer à ce fichier de log. Il suffit de préciser l'expression régulière au sein du paramètre -Pattern :

Select-String -Path "C:\TEMP\GREP\access.log" -Pattern "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"

Ce qui donne :

Rechercher toutes les adresses IP présentes dans un fichier

Suite à cette recherche, on pourrait facilement obtenir la liste de toutes les adresses IP référencées dans ce fichier. Pour cela, il faut regarder au sein des différents matchs de la Regex avec une boucle sur $_.Matches et une seconde boucle pour récupérer la valeur de chaque match. Ce qui donne la commande suivante :

Select-String -Path "C:\TEMP\GREP\access.log" -Pattern "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" | Foreach{ $_.Matches } | Foreach{ $_.Value }

Ensuite, on obtient la liste des adresses IP trouvées dans le fichier access.log :

On pourrait affiner notre pattern et rechercher toutes les requêtes qui correspondent à un réseau IP spécifique, ou qui commence d'une certaine façon. Par exemple, pour rechercher toutes les requêtes (c'est-à-dire toutes les lignes) où l'on trouve une adresse IP sous la forme "211.X.X.X", on fera :

Select-String -Path "C:\TEMP\GREP\access.log" -Pattern "211.\d{1,3}.\d{1,3}\.\d{1,3}"

De la même façon, on pourrait rechercher toutes les lignes avec une adresse IP sous la forme "192.168.X.X" :

Select-String -Path "C:\TEMP\GREP\access.log" -Pattern "192.168.\d{1,3}\.\d{1,3}"

Voilà, c'est la fin du dernier exemple sur l'utilisation de Select-String. Mais ce n'est pas terminé, il nous reste un petit bonus à découvrir.

IV. Bonus : créer un alias grep pour Select-String

Vous aimeriez pouvoir saisir "grep" plutôt que "Select-String" ? Alors j'ai une solution pour vous : la création d'un alias !

Il suffit de créer un alias de cette façon :

New-Alias grep Select-String

Ensuite, on peut utiliser grep à la place de Select-String, mais les paramètres restent les mêmes, bien entendu.

grep -Path "C:\TEMP\GREP\access.log" -Pattern "127.0.\d{1,3}\.\d{1,3}"
Créer un alias grep pour la commande Select-String

Attention, cet alias sera temporaire : lorsque la console PowerShell sera fermée, il sera supprimé. Pour le rendre persistant, je vous invite à lire mon tutoriel sur les alias en PowerShell : PowerShell - Alias

N'hésitez pas à partager vos astuces avec Select-String en PowerShell en postant un commentaire sur cet article ! 😉

author avatar
Florian BURNEL Co-founder of IT-Connect
Ingénieur système et réseau, cofondateur d'IT-Connect et Microsoft MVP "Cloud and Datacenter Management". Je souhaite partager mon expérience et mes découvertes au travers de mes articles. Généraliste avec une attirance particulière pour les solutions Microsoft et le scripting. Bonne lecture.
Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Envoyer par mail

1 commentaire sur “PowerShell grep : rechercher des chaînes de caractères avec Select-String

  • au top ces petits tips.
    Merci florian 😉

    Répondre

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.