Problemas de expresión regular de PowerShell

Oct 16 2020

Esta es mi primera publicación, tiendo a poder encontrar lo que necesito leyendo y buscando otras publicaciones, pero esta me ha derrotado. Estoy tratando de usar una expresión regular en Powershell para buscar datos en un archivo de texto.

Archivo de texto de muestra: (hay espacios en el archivo de texto de muestra hasta el final de esa línea)

 Impression            CONCLUSION:                                                                     
 Impression                        
            
 Impression            CONCLUSION:                                                                     
 Impression            SomeData

 Impression            CONCLUSION:                                                                     
 Impression            SomeOtherData

 Impression            CONCLUSION:                                                                     
 Impression                                         

Estoy buscando dónde está la segunda línea en blanco después de la línea con la conclusión.

Esta fue la base de mi simple intento:

Get-Content -Path "C:\temp\Log\Conclusion.txt" | Select-String -Pattern "CONCLUSION:\s*\r\n\s*Impression\s*\r\n\s*Impression" -Context 1, 1

Descubrí que cualquier cosa con \ r \ n no devolvería ningún resultado. Probé tanto \ r como \ n por su cuenta, intenté Obtener contenido como Raw, pero eso solo genera el archivo completo nuevamente. Se agradece la ayuda, gracias.

Actualización: Gracias por las respuestas de todos, debería haber especificado que estaba intentando encontrar líneas después de la conclusión que estaban vacías. Terminé obteniendo un recuento para comenzar con el uso de Get-Content -Raw. Mis datos de muestra cambiaron levemente para agregar otra línea en blanco con la palabra impresión: Nombre / Ubicación Impresión CONCLUSIÓN:
Impresión Impresión

Este código fue capaz de obtener un recuento: (extraído / modificado de otra publicación del foro, no me atribuyo el mérito de haberlo creado)

$ search_string = "\ s CONCLUSIÓN: \ s \ r \ n \ s Impresión \ s \ r \ n \ s Impresión \ s \ r \ n \ s Impresión \ s \ r \ n" $ file_path = "C: \ temp \ Log \ Conclusion.txt "$string = (Get-Content -raw -Path $file_path | Seleccionar cadena$search_string -AllMatches | % { $_.matches}). count

Todavía estoy trabajando en una forma de imprimir algunos datos más que solo funcionarían cuando no use Raw, había planeado usar el contexto para tomar la conclusión de la línea anterior, pero dado que Raw trae todo en una línea, eso no funciona. Gracias de nuevo por la ayuda, si alguien tiene más consejos sobre cómo usar \ r \ ny no usar Raw, hágamelo saber.

Respuestas

paddywan Oct 16 2020 at 20:50

No estoy seguro de qué tan bien funcionará esto con powershell, pero dale una oportunidad: (*CRLF)CONCLUSION:\sImpression\s\s

https://regex101.com/r/d6Pm2k/1

Brian Oct 16 2020 at 21:46

Aquí está mi feo ataque de fuerza bruta:

$blankRows = @() $targetRows = @()
$rowNum = 0 $foundRows = @()

$myFile = Get-Content $thisFile

Foreach($thisRow in $myFile){
    $rowNum++ if($thisRow -eq "Impression"){$blankRows += $rowNum}
    if ($thisRow -match 'CONCLUSION'){$targetRows += $rowNum} } Foreach($blrw in $blankRows){ if ($targetRows -contains ($blrw-1)){$foundRows += $blrw} } $foundRows
postanote Oct 17 2020 at 23:16

¿Por qué no hacer esto?

# Create some sample data file
@'
Impression CONCLUSION:
Impression

Impression CONCLUSION:
Impression SomeData

Impression CONCLUSION:
Impression SomeOtherData

Impression CONCLUSION:
Impression
'@ | 
Out-File -FilePath 'D:\Temp\Imprestion.txt' -Force
Get-Content -Path 'D:\Temp\Imprestion.txt'
# Results
<#
Impression CONCLUSION:
Impression

Impression CONCLUSION:
Impression SomeData

Impression CONCLUSION:
Impression SomeOtherData

Impression CONCLUSION:
Impression
#>

# Import the sample data file as a CSV, use the space as a Delimiter
Import-Csv -Path 'D:\Temp\Imprestion.txt' -Delimiter ' ' -Header Property, Value
# Results
<#
Property   Value        
--------   -----        
Impression CONCLUSION:  
Impression              
Impression CONCLUSION:  
Impression SomeData     
Impression CONCLUSION:  
Impression SomeOtherData
Impression CONCLUSION:  
Impression              
#>

# Filter by the Value property
Import-Csv -Path 'D:\Temp\Imprestion.txt' -Delimiter ' ' -Header Property, Value | 
Where-Object -Property Value -EQ $null # Results <# Property Value -------- ----- Impression Impression #> # Using Select-String and a RegEx 'Not Match' Select-String -Path 'D:\Temp\Imprestion.txt' -Pattern '^((?!Impression [a-zA-Z]).)*$'
# Results
<#
D:\Temp\Imprestion.txt:2:Impression
D:\Temp\Imprestion.txt:3:
D:\Temp\Imprestion.txt:6:
D:\Temp\Imprestion.txt:9:
D:\Temp\Imprestion.txt:11:Impression
#>

# Using Select-String and RegEx match
Select-String -Path 'D:\Temp\Imprestion.txt' -Pattern '^Impression\s*$'
# Results
<#
D:\Temp\Imprestion.txt:2:Impression
D:\Temp\Imprestion.txt:11:Impression
#>

Explicación:

  • ^ es el comienzo del ancla de cadena.
  • $ es el final del ancla de cadena.
  • \ s es la clase de caracteres de espacio en blanco.
  • es cero o más repetición de.
KeithMiller Oct 17 2020 at 04:25

Todavía no estoy seguro de qué es exactamente lo que desea capturar, las líneas completamente en blanco o las que Impressionno tienen datos a continuación.

Pero según la documentación, Get-Contnet :

  • Para los archivos, el contenido se lee una línea a la vez y devuelve una colección de objetos, cada uno de los cuales representa una línea de contenido.

Así que los <newline>caracteres se "consumen" como separadores de elementos de una matriz de cadenas.
Tratar:

Get-Content -Path "C:\temp\Log\Conclusion.txt" | gm
(Get-Content -Path "C:\temp\Log\Conclusion.txt").Count

por lo que nunca coincidirá <newline>con el código tal como está escrito.

Puede usar el -Rawparámetro para tratar el archivo como una cadena larga con <newline>caracteres o reescribir su lógica para buscar una matriz.


Además, la documentación de Select-string muestra que puede tomar un archivo directamente y procesarlo línea por línea, sin necesidad de Get-Content.


Actualizar

Todavía no estoy seguro de qué línea desea generar, pero aquí hay una muestra esquemática de lo que creo que está pidiendo. Mis suposiciones son:

  • Las líneas que busca son las que no tienen texto después de "Impresión" (aclare si es literal o de datos)
  • Cuando se encuentra una coincidencia, se captura la línea anterior para el archivo de salida.
$File = Get-Content -Path "C:\temp\Log\Conclusion.txt" $OutLines   = @()
$EmptyMatch = '^Impression\s*$'
$i = 0 ForEach ( $line in $File ) { If ( $line -match $EmptyMatch ) { $OutLines += $File[ $i - 1 ]
    }
    $i++ } $OutLines | Set-Content 'c:\MyStuff\OutFile.txt'
Add