Le espressioni regolari di PowerShell hanno problemi
Questo è il mio primo post, tendo a trovare quello che mi serve leggendo e cercando altri post, ma questo mi ha sconfitto. Sto cercando di utilizzare un'espressione regolare in Powershell per cercare dati in un file di testo.
File di testo di esempio: (ci sono spazi nel file di testo di esempio fino alla fine di quella riga)
Impression CONCLUSION:
Impression
Impression CONCLUSION:
Impression SomeData
Impression CONCLUSION:
Impression SomeOtherData
Impression CONCLUSION:
Impression
Sto cercando di trovare dove la seconda riga è vuota dopo la riga con la conclusione.
Questa è stata la base del mio semplice tentativo:
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
Ho scoperto che qualsiasi cosa con \ r \ n non restituisce alcun risultato. Ho provato entrambi \ r e \ n da soli, ho tentato di ottenere il contenuto come Raw, ma questo restituisce nuovamente l'intero file. L'aiuto è apprezzato, grazie.
Aggiornamento: grazie per le risposte di tutti, avrei dovuto specificare che stavo tentando di trovare righe dopo la conclusione che erano vuote. Ho finito per ottenere un conteggio per lavorare per i principianti utilizzando Get-Content -Raw. I miei dati di esempio sono cambiati leggermente per aggiungere un'altra riga vuota con la parola impressione: nome / posizione impressione CONCLUSIONE:
impressione impressione
Questo codice è stato in grado di farmi un conteggio: (estratto / modificato da un altro post del forum, non mi prendo il merito di averlo inventato)
$ search_string = "\ s CONCLUSIONE: \ s \ r \ n \ s Impression \ s \ r \ n \ s Impression \ s \ r \ n \ s Impression \ s \ r \ n" $ file_path = "C: \ temp \ Log \ Conclusion.txt "$string = (Get-Content -raw -Path $file_path | Select-String$search_string -AllMatches | % { $_.matches}). count
Sto ancora lavorando a un modo per stampare altri dati che funzionerebbero solo quando non si utilizza Raw, avevo pianificato di utilizzare il contesto per afferrare la riga sopra la conclusione, ma poiché raw riunisce tutto in una riga, ciò non funziona. Grazie ancora per l'aiuto, se qualcuno ha altri suggerimenti su come usare \ r \ ne non usare Raw, fammelo sapere.
Risposte
Non sono sicuro di quanto funzionerà bene con PowerShell, ma provalo: (*CRLF)CONCLUSION:\sImpression\s\s
https://regex101.com/r/d6Pm2k/1
Ecco il mio brutto attacco di forza 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
Perché non farlo semplicemente?
# 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
#>
Spiegazione:
- ^ è l'inizio dell'ancora di stringa.
- $ è la fine dell'ancora di stringa.
- \ s è la classe di caratteri dello spazio vuoto.
- è zero o più ripetizioni di.
Non sono ancora sicuro di cosa vuoi catturare, le righe completamente vuote o quelle con Impressione nessun dato che segue.
Ma secondo la documentazione, Get-Contnet :
- Per i file, il contenuto viene letto una riga alla volta e restituisce una raccolta di oggetti, ognuno dei quali rappresenta una riga di contenuto.
COSÌ i <newline>caratteri vengono "consumati" come separatori di elementi di un array di stringhe.
Provare:
Get-Content -Path "C:\temp\Log\Conclusion.txt" | gm
(Get-Content -Path "C:\temp\Log\Conclusion.txt").Count
quindi non abbinerai mai a <newline>con il codice come scritto.
È possibile utilizzare il -Rawparametro per trattare il file come una lunga stringa di <newline>caratteri o riscrivere la logica per la ricerca in un array.
Inoltre, la documentazione per Select-string mostra che può prendere un file direttamente ed elaborarlo riga per riga, senza bisogno di Get-Content.
Aggiornare
Non sono ancora sicuro di quale riga si desidera produrre, ma ecco un esempio scheletrico di ciò che penso tu stia chiedendo. Le mie ipotesi sono:
- Le righe che stai cercando sono quelle senza testo dopo "Impressione" (chiarisci se questo è letterale o dati)
- Quando viene trovata una corrispondenza, la riga precedente viene acquisita per il file di output.
$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