Problemy z wyrażeniami regularnymi programu PowerShell

Oct 16 2020

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

paddywan Oct 16 2020 at 20:50

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

Brian Oct 16 2020 at 21:46

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
postanote Oct 17 2020 at 23:16

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ń.
KeithMiller Oct 17 2020 at 04:25

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