Проблемы с регулярными выражениями PowerShell

Oct 16 2020

Это мой первый пост, я, как правило, могу найти то, что мне нужно, читая и просматривая другие сообщения, но этот меня побеждал. Я пытаюсь использовать регулярное выражение в Powershell для поиска данных в текстовом файле.

Пример текстового файла: (В образце текстового файла до конца строки есть пробелы)

 Impression            CONCLUSION:                                                                     
 Impression                        
            
 Impression            CONCLUSION:                                                                     
 Impression            SomeData

 Impression            CONCLUSION:                                                                     
 Impression            SomeOtherData

 Impression            CONCLUSION:                                                                     
 Impression                                         

Я ищу, где вторая строка пуста после строки с заключением.

Это было основой моей простой попытки:

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

Я обнаружил, что Anything with \ r \ n не вернет никаких результатов. Я попробовал как \ r, так и \ n по отдельности, я попытался получить контент как Raw, но это просто снова выводит весь файл. Помощь приветствуется, спасибо.

Обновление: спасибо за все ответы, я должен был указать, что пытался найти пустые строки после вывода. Я закончил тем, что начал работать с счетчиком с помощью Get-Content -Raw. Мои выборочные данные немного изменить , чтобы добавить еще одну пустую строку со словом впечатление: Имя / Расположение Impression ВЫВОД:
Impression Impression

Этот код позволил мне подсчитать: (извлечено / изменено из другого сообщения на форуме, я не беру на себя ответственность за это)

$ search_string = "\ s ВЫВОД: \ s \ r \ n \ s Впечатление \ s \ r \ n \ s Впечатление \ s \ r \ n \ s Впечатление \ s \ r \ n" $ file_path = "C: \ temp \ Log \ Conclusion.txt "$string = (Get-Content -raw -Path $file_path | Выбрать строку$search_string -AllMatches | % { $_.matches}). count

Я все еще работаю над способом распечатать еще несколько данных, которые будут работать только без использования Raw, я планировал использовать контекст, чтобы захватить строку выше вывода, но, поскольку raw объединяет все в одну строку, это не работает. Еще раз спасибо за помощь, если у кого-то есть еще советы о том, как можно использовать \ r \ n и не использовать Raw, дайте мне знать.

Ответы

paddywan Oct 16 2020 at 20:50

Я не уверен, насколько хорошо это будет работать с PowerShell, но попробуйте: (*CRLF)CONCLUSION:\sImpression\s\s

https://regex101.com/r/d6Pm2k/1

Brian Oct 16 2020 at 21:46

Вот моя уродливая атака грубой силой:

$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

Почему бы просто не сделать это?

# 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
#>

Пояснение:

  • ^ - начало привязки строки.
  • $ - конец привязки строки.
  • \ s - это класс символов пробела.
  • - это ноль или более повторений.
KeithMiller Oct 17 2020 at 04:25

Я до сих пор не совсем уверен, что именно вы хотите записать: полностью пустые строки или строки, за которыми Impressionне следуют данные.

Но согласно документации Get-Contnet :

  • Для файлов содержимое считывается по одной строке за раз и возвращает набор объектов, каждый из которых представляет собой строку содержимого.

ТАК <newline>символы "потребляются" как разделители элементов строкового массива.
Пытаться:

Get-Content -Path "C:\temp\Log\Conclusion.txt" | gm
(Get-Content -Path "C:\temp\Log\Conclusion.txt").Count

так что вы никогда не сопоставите a <newline>с написанным кодом.

Вы можете использовать -Rawпараметр, чтобы рассматривать файл как одну длинную строку с <newline>символами или переписать логику поиска в массиве.


Кроме того, документация для Select-string показывает, что он может напрямую брать файл и обрабатывать его построчно, без необходимости Get-Content.


Обновить

Я все еще не уверен, какую строку вы хотите вывести, но вот скелетный образец того, что, я думаю, вы просите. Мои предположения:

  • Строки, которые вы ищете, - это строки без текста после слова "Impression" (пожалуйста, поясните, является ли это буквальным или буквальным)
  • Когда совпадение найдено, предыдущая строка захватывается для выходного файла.
$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