2009-03-05 5 views
18

Tengo un archivo de texto que contiene líneas de datos. Puedo utilizar el siguiente script de PowerShell para extraer las líneas que me interesan:Cómo extrae el valor de una referencia regex/coincidencia en Powershell

select-string -path *.txt -pattern "subject=([A-Z\.]+)," 

Algunos datos de ejemplo serían:

blah blah subject=THIS.IS.TEST.DATA, blah blah blah 

Lo que yo quiero es ser capaz de extraer sólo los contenidos reales del sujeto (es decir, la cadena "THIS.IS.TEST.DATA"). Intenté esto:

select-string -path *.txt -pattern "subject=([A-Z\.]+)," | %{ $_.Matches[0] } 

Pero la propiedad "Coincidencias" es siempre nula. ¿Qué estoy haciendo mal?

Respuesta

9

No sé por qué su versión no funciona. Deberia de funcionar. Aquí hay una versión más fea que funciona.

$p = "subject=([A-Z\.]+)," 
select-string -path *.txt -pattern $p | % {$_ -match $p > $null; $matches[1]} 

Editar. Explicación de dant:

-match es un operador de expresión regular coincidente:

>"foobar" -match "oo.ar" 
True 

El > $null simplemente suprime el Verdadero están escribiendo en la salida. (Intente eliminarlo). Hay un cmdlet que hace lo mismo cuyo nombre no recuerdo en este momento.

$matches es una variable mágica que contiene el resultado de la última operación -match.

+0

Gracias, eso funciona, pero ¿podría explicarme lo que está haciendo? Particularmente el bit "$ _-match $ p> $ null". – d4nt

+1

El cmdlet dangph que está pensando es "Out-Null". Pero también puede convertir toda la línea en [void]: [void] ($ _ -match $ p) – JasonMArcher

2

El problema con el código que está escribiendo es que select-string no pasa el objeto Regex real. En su lugar, pasa una clase diferente llamada MatchInfo que no tiene la información real de correspondencias reales.

Si solo desea ejecutar la expresión regular una vez, tendrá que activar su propia función, que no es demasiado difícil.

function Select-Match() { 
    param ($pattern = $(throw "Need a pattern"), 
     $filePath = $(throw "Need a file path")) 
    foreach ($cur in (gc $filePath)) { 
    if ($cur -match $pattern) { 
     write-output $matches[0]; 
    } 
    } 
} 

gci *.txt | %{ Select-Match "subject=([A-Z\.]+)," $_.FullName } 
+0

¿Pero por qué la propiedad MatchInfo.Matches no funciona? http://msdn.microsoft.com/en-us/library/microsoft.powershell.commands.matchinfo.matches(VS.85).aspx –

+0

@dangph, creo que es un error en los documentos. Puede verificar esto ejecutando "gci a * .txt | gm". El tipo resultante no tiene ninguna propiedad de coincidencias. – JaredPar

+0

JaredPar, eso no funcionó para mí, pero creo que tienes razón. Pruebe esto: "gm -inputobject (new-object Microsoft.PowerShell.Commands.MatchInfo)". –

2

Sin embargo, otra opción

gci *.txt | foreach { [regex]::match($_,'(?<=subject=)([^,]+)').value } 
2

Después de haber aprendido mucho de todas las otras respuestas que era capaz de conseguir lo que quiero usar la siguiente línea:

gci *.txt | gc | %{ [regex]::matches($_, "subject=([A-Z\.]+),") } | %{ $_.Groups[1].Value } 

esto se sentía bien como Solo estaba ejecutando la expresión regular una vez por línea y cuando ingresé esto en el símbolo del sistema, fue bueno no tener varias líneas de código.

+0

Me alegro de que hayas encontrado una solución. Acabo de registrar v2 y la propiedad Coincidencias funciona desde Select-String. Entonces en el futuro esto será menos doloroso para ti. :) – JasonMArcher

0

Otra variación, igualando 7 dígitos en una cadena

echo "123456789 hello test" | % {$_ -match "\d{7}" > $null; $matches[0]} 

devuelve: 1234567

4

En PowerShell V2 CTP3, la propiedad Partidos se implementa.Por lo que el siguiente trabajo:

select-string -path *.txt -pattern "subject=([A-Z\.]+)," | %{ $_.Matches[0].Groups[1].Value } 
1

El comando Select-String parece volver una Matchinfo variable y no una "cadena" variable. Pasé varias horas descubriendo esto en foros y sitios web oficiales sin suerte. Todavía estoy recopilando información. Una forma de evitar esto es declarar explícitamente una variable de cadena para mantener el resultado devuelto desde el Select-String, de su ejemplo:

[cadena] $ foo = select-string -path * .txt -pattern " subject = ([AZ.] +), "

La variable $ foo ahora es una cadena y no un objeto MatchInfo.

Espero que esto ayude.

ps5 powershell versión 5 cuerdas de cadena manipulación

Cuestiones relacionadas