A expressão regular do PowerShell tem dificuldades
Esta é a minha primeira postagem, tendo a ser capaz de encontrar o que preciso lendo e pesquisando outras postagens, mas esta me derrotou. Estou tentando usar uma expressão regular no Powershell para procurar dados em um arquivo de texto.
Arquivo de texto de amostra: (há espaços no arquivo de texto de amostra até o final dessa linha)
Impression CONCLUSION:
Impression
Impression CONCLUSION:
Impression SomeData
Impression CONCLUSION:
Impression SomeOtherData
Impression CONCLUSION:
Impression
Estou procurando encontrar onde a segunda linha está em branco após a linha com a conclusão.
Esta foi a base da minha tentativa simples:
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
Descobri que qualquer coisa com \ r \ n não retornaria nenhum resultado. Tentei \ r e \ n por conta própria, tentei obter o conteúdo como Raw, mas isso apenas retorna o arquivo inteiro novamente. A ajuda é apreciada, obrigado.
Atualização: Obrigado pelas respostas de todos, eu deveria ter especificado que estava tentando encontrar linhas após a conclusão que estavam vazias. Acabei fazendo uma contagem funcionar para começar usando Get-Content -Raw. Meus dados de amostra mudaram ligeiramente para adicionar outra linha em branco com a palavra impressão: Nome / Local Impressão CONCLUSÃO:
Impressão Impressão
Este código foi capaz de obter uma contagem: (extraído / modificado de outra postagem do fórum, não recebo os créditos por sugerir isso)
$ search_string = "\ s CONCLUSÃO: \ s \ r \ n \ s Impressão \ s \ r \ n \ s Impressão \ s \ r \ n \ s Impressão \ s \ r \ n" $ file_path = "C: \ temp \ Log \ Conclusion.txt "$string = (Get-Content -raw -Path $file_path | Select-String$search_string -AllMatches | % { $_.matches}). count
Ainda estou trabalhando em uma maneira de imprimir mais alguns dados que só funcionariam sem o Raw, planejei usar o contexto para pegar a conclusão da linha acima, mas como o raw traz tudo em uma linha, isso não funciona. Obrigado novamente pela ajuda, se alguém tiver mais dicas sobre como usar \ r \ n e não usar Raw, por favor me avise.
Respostas
Não tenho certeza se isso vai funcionar bem com o PowerShell, mas tente: (*CRLF)CONCLUSION:\sImpression\s\s
https://regex101.com/r/d6Pm2k/1
Aqui está meu feio ataque de força 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 que simplesmente não fazer isso?
# 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
#>
Explicação:
- ^ é o início da âncora de string.
- $ é o fim da âncora da string.
- \ s é a classe de caractere de espaço em branco.
- é zero ou mais repetição de.
Ainda não tenho certeza do que você quer capturar, as linhas completamente em branco ou aquelas com Impressione sem dados seguindo.
Mas de acordo com a documentação, Get-Contnet :
- Para arquivos, o conteúdo é lido uma linha de cada vez e retorna uma coleção de objetos, cada um representando uma linha de conteúdo.
ASSIM, os <newline>caracteres são "consumidos" como separadores de elementos de uma matriz de string.
Experimentar:
Get-Content -Path "C:\temp\Log\Conclusion.txt" | gm
(Get-Content -Path "C:\temp\Log\Conclusion.txt").Count
portanto, você nunca combinará a <newline>com o código escrito.
Você pode usar o -Rawparâmetro para tratar o arquivo como uma longa string com <newline>caracteres ou reescrever sua lógica para pesquisar um array.
Além disso, a documentação do Select-string mostra que ele pode pegar um arquivo diretamente e processá-lo linha por linha, sem necessidade Get-Content.
Atualizar
Ainda não tenho certeza de qual linha você deseja imprimir, mas aqui está uma amostra do esqueleto do que acho que você está pedindo. Minhas suposições são:
- As linhas que você está procurando são aquelas sem texto após "Impressão" (esclareça se isso é literal ou dados)
- Quando uma correspondência é encontrada, a linha anterior é capturada para o arquivo de saída.
$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