2010-10-13 7 views
19

Je voudrais rechercher plus d'une chaîne dans les fichiers dans un répertoire, mais en utilisant "select-string -pattern" n'a pas aidé. Quelqu'un pourrait-il me montrer comment le faire?Comment utiliser PowerShell select-string pour trouver plus d'un motif dans un fichier?

Exemple: Rechercher tous les fichiers dans C: \ logs qui contiennent les mots « VendorEnquiry » et « Échec », et avec un Logtime vers 11h30. La structure des fichiers peut différer (par exemple, différents noms de point, etc.):

... <methodException>VendorEnquiry</methodException> ... 
... <logTime>13/10/2010T11:30:04 am</logTime> ... 
... <status>Failed</status> ... 

... <serviceMethodException>VendorEnquiry</serviceMethodException> ... 
... <logTime>13/10/2010</logTime> ... 
... <serviceStatus>Failed</serviceStatus> ... 

Merci.

Répondre

0
+0

Je ne veux pas utiliser l'analyse syntaxique xml a causé des performances très lent pour les fichiers énormes journaux. Je veux quelque chose qui va vite. Regex est bon mais je ne sais pas comment je peux écrire l'expression que la recherche dans le fichier où il existe un mot VendorEnquiry et Failed existe. – Thomas

22

Si vous voulez faire correspondre les deux mots soit l'ordre, utilisez:

gci C:\Logs| select-string -pattern '(VendorEnquiry.*Failed)|(Failed.*VendorEnquiry)' 

En cas d'échec vient toujours après VendorEnquiry sur la ligne, il suffit d'utiliser:

gci C:\Logs| select-string -pattern '(VendorEnquiry.*Failed)' 
16

Pour rechercher plusieurs correspondances dans chaque fichier, nous pouvons séquencer plusieurs appels Select-String:

Get-ChildItem C:\Logs | 
    where { $_ | Select-String -Pattern 'VendorEnquiry' } | 
    where { $_ | Select-String -Pattern 'Failed' } | 
    ... 

A chaque étape, les fichiers qui ne contiennent pas le modèle courant seront filtrés, garantissant que la liste finale des fichiers contient tous les termes de recherche.

Plutôt que d'écrire chaque appel Select-String manuellement, nous pouvons simplifier cela avec un filtre pour correspondre à plusieurs modèles:

filter MultiSelect-String([string[]]$Patterns) { 
    # Check the current item against all patterns. 
    foreach($Pattern in $Patterns) { 
    # If one of the patterns does not match, skip the item. 
    $matched = @($_ | Select-String -Pattern $Pattern) 
    if(-not $matched) { 
     return 
    } 
    } 

    # If all patterns matched, pass the item through. 
    $_ 
} 

Get-ChildItem C:\Logs | MultiSelect-String 'VendorEnquiry','Failed',... 


Maintenant, pour satisfaire la partie « Logtime vers 11h30 » de l'exemple nécessiterait de trouver l'heure du journal correspondant à chaque entrée d'échec. Comment faire cela dépend fortement de la structure réelle des fichiers, mais les tests pour « environ » est relativement simple:

function AboutTime([DateTime]$time, [DateTime]$target, [TimeSpan]$epsilon) { 
    $time -le ($target + $epsilon) -and $time -ge ($target - $epsilon) 
} 

PS> $epsilon = [TimeSpan]::FromMinutes(5) 
PS> $target = [DateTime]'11:30am' 
PS> AboutTime '11:00am' $target $epsilon 
False 
PS> AboutTime '11:28am' $target $epsilon 
True 
PS> AboutTime '11:35am' $target $epsilon 
True