2010-10-13 24 views
19

Me gustaría buscar más de una cadena en los archivos de un directorio, sin embargo, el uso de "select-string -pattern" no me ayudó. ¿Alguien podría mostrarme cómo hacerlo?¿Cómo usar PowerShell select-string para encontrar más de un patrón en un archivo?

Ejemplo: Buscar todos los archivos en C: \ Los registros que contienen las palabras "VendorEnquiry" y "Failed", y con un Logtime alrededor de las 11:30 a.m. La estructura de los archivos puede diferir (por ejemplo, diferentes nombres de etiquetas, 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> ... 

Gracias.

Respuesta

0
+0

No quiero utilizar el análisis de XML causó un rendimiento muy lento para grandes archivos de registro. Quiero algo tan rápido. Regex es bueno, pero no sé cómo puedo escribir la expresión que busca en el archivo donde existe una palabra VendorEnquiry and Failed. – Thomas

22

Si desea hacer coincidir las dos palabras en cualquier orden, en uso:

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

Si Falló siempre viene después de VendorEnquiry en la línea, sólo tiene que utilizar:

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

Para buscar múltiples coincidencias en cada archivo, podemos secuenciar varias llamadas a Select-String:

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

En cada paso, se filtrarán los archivos que no contengan el patrón actual, asegurándose de que la lista final de archivos contenga todos los términos de búsqueda.

En lugar de escribir cada llamada Select-String manualmente, podemos simplificar esto con un filtro para que coincida con múltiples patrones:

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',... 


Ahora, para satisfacer el "LogTime alrededor de las 11:30 am" parte del ejemplo requeriría encontrar el tiempo de registro correspondiente a cada entrada de falla. Cómo hacer esto depende de la estructura real de los archivos muy, pero las pruebas de "aproximadamente" es relativamente 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 
Cuestiones relacionadas