Problemas de expresión regular de PowerShell
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
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
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
¿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.
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