Problemy z wyrażeniami regularnymi programu PowerShell
To mój pierwszy post. Zwykle jestem w stanie znaleźć to, czego potrzebuję, czytając i przeszukując inne posty, ale ten mnie pokonał. Próbuję użyć wyrażenia regularnego w programie PowerShell, aby wyszukać dane w pliku tekstowym.
Przykładowy plik tekstowy: (w przykładowym pliku tekstowym są spacje do końca tej linii)
Impression CONCLUSION:
Impression
Impression CONCLUSION:
Impression SomeData
Impression CONCLUSION:
Impression SomeOtherData
Impression CONCLUSION:
Impression
Szukam, gdzie druga linia jest pusta po linii z wnioskiem.
To była podstawa mojej prostej próby:
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
Zauważyłem, że Cokolwiek z \ r \ n nie zwróci żadnych wyników. Próbowałem zarówno \ r, jak \ n samodzielnie, próbowałem pobrać zawartość jako surową, ale to po prostu ponownie wyświetla cały plik. Dziękujemy za pomoc.
Aktualizacja: Dzięki za odpowiedzi wszystkich, powinienem był sprecyzować, że próbowałem znaleźć wiersze po zakończeniu, które były puste. Skończyło się na tym, że zacząłem liczyć na początek przy użyciu Get-Content -Raw. Moje przykładowe dane nieznacznie zmienione, aby dodać kolejny pusty wiersz z wrażenia słowo: Nazwa / lokalizacja Impression Wniosek:
Wrażenie Wrażenie
Ten kod był w stanie uzyskać wynik: (wyciągnięty / zmodyfikowany z innego posta na forum, nie biorę kredytu za wymyślenie tego)
$ search_string = "\ s WNIOSEK: \ 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 $ścieżka_pliku | Wybierz ciąg$search_string -AllMatches | % { $_.matches}). count
Nadal pracuję nad sposobem wydrukowania większej ilości danych, które działałyby tylko wtedy, gdy nie używam Raw, planowałem użyć kontekstu, aby złapać wiersz powyżej wniosku, ale ponieważ surowe przenosi wszystko w jednej linii, to nie działa. Jeszcze raz dziękuję za pomoc. Jeśli ktoś ma więcej wskazówek dotyczących używania \ r \ n i nie używania Raw, daj mi znać.
Odpowiedzi
Nie jestem pewien, jak dobrze to zadziała z PowerShell, ale daj temu szansę: (*CRLF)CONCLUSION:\sImpression\s\s
https://regex101.com/r/d6Pm2k/1
Oto mój brzydki atak brutalnej siły:
$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
Dlaczego po prostu tego nie zrobić?
# 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
#>
Wyjaśnienie:
- ^ jest początkiem kotwicy łańcucha.
- $ jest końcem kotwicy łańcucha.
- \ s to klasa białych znaków.
- to zero lub więcej powtórzeń.
Nadal nie jestem pewien, co chcesz uchwycić, zupełnie puste linie lub te, które nie zawierają Impressionżadnych danych.
Ale zgodnie z dokumentacją Get-Contnet :
- W przypadku plików treść jest odczytywana po jednym wierszu na raz i zwraca kolekcję obiektów, z których każdy reprezentuje wiersz treści.
Więc <newline>znaki są "konsumowane" jako separatory elementów tablicy łańcuchowej.
Próbować:
Get-Content -Path "C:\temp\Log\Conclusion.txt" | gm
(Get-Content -Path "C:\temp\Log\Conclusion.txt").Count
więc nigdy nie dopasujesz a <newline>z napisanym kodem.
Możesz użyć parametru -Rawparamaeter, aby traktować plik jako jeden długi łańcuch ze <newline>znakami lub ponownie napisać logikę wyszukiwania tablicy.
Również dokumentacja dla Select-string pokazuje, że może on pobierać plik bezpośrednio i przetwarzać go wiersz po wierszu, bez potrzeby Get-Content.
Aktualizacja
Nadal nie jestem pewien, którą linię chcesz wyświetlić, ale oto próbka szkieletu tego, o co myślę . Moje założenia są następujące:
- Poszukiwane wiersze to te, które nie zawierają tekstu po wyrażeniu „Wyświetlenie” (sprecyzuj, czy jest to literał, czy dane)
- Po znalezieniu dopasowania poprzednia linia jest przechwytywana dla pliku wyjściowego.
$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