Строка выбора с Regex и разделением / выводом на несколько файлов - PullRequest
2 голосов
/ 06 октября 2019

Добрый день всем

Хотел бы посоветоваться о том, что я сделал неправильно в строке выбора / регулярном выражении. Когда регулярное выражение с шаблоном '(?m)(abc)(.*?)(--- End ---)' было проверено на Notepad ++, оно работает (поля были выделены правильно), но каким-то образом, когда я поместил его в Powershell для выполнения, он возвращает нулевой результат.

Если бы я изменил регулярное выражение на '(?m)(abc)(.*?)', он извлечет весь контент со строки 1 до строки 12.

Я хочу захватить и иметь возможность разбить результат на 3 файла результатов. Файл1 - (Содержимое от Строки1 до Строки4) Файл2 - (Содержимое Строки5 до Строки8) Файл3 - (Содержимое Строки9 до Строки12

Broken Command that i used:
While (line is not equal to end of file) {
Get-ChildItem "C:\Users\ASUS\Desktop\Pscript\test-script.txt" | ForEach {
$getctnt = Get-Content $_.FullName
$getctnt | Select-String -Pattern '(?m)(abc)(.*?)(--- End ---)' | Out-File .\result$a.txt
$a++
}
}

Content of the Test-script.txt:
Line1       abc
Line2       content1
Line3       conten2
Line4       --- End ---
Line5       abc
Line6       content1
Line7       content2
Line8       --- End ---
Line9       abc
Line10      content1
Line11      content2
Line12      --- End ---

Ответы [ 3 ]

1 голос
/ 06 октября 2019

Проблема с вашей попыткой связана с неправильным чтением Test-script.txt. Когда вы запускаете команду Get-Content без ключа -Raw, файл читается как массив строк. Когда это передано в Select-String, команда будет обрабатывать только одну строку за раз и ничего не будет знать о предыдущих или следующих строках. Если вы реализуете ключ -Raw, он будет считываться в файле как одна строка. Затем вы можете перейти на Select-String и соответствовать символам новой строки. С учетом вышесказанного вам необходимо включить однострочный модификатор (?s), чтобы . соответствовал \n и \r символам. Поскольку у вас есть несколько совпадений для одного и того же шаблона регулярных выражений, вам необходимо добавить переключатель -AllMatches.

$getctnt = Get-Content $_.FullName -Raw
$selections = $getctnt | Select-String -Pattern '(?s)(abc)(.*?)(--- End ---)' -AllMatches

$selections теперь будет содержать массив объектов MatchInfo, которые можно перебирать или индексировать на основена ваших требованиях. Ниже описан способ доступа к этим значениям.

$selections.Matches # For the MatchInfo objects
$selections.Matches.Value # For the matched values

Поскольку вы использовали несколько наборов скобок, вы создали 4 группы захвата (0,1,2,3) и три полных совпадения. Я не знаю, было ли это вашим намерением, но они также доступны. Чтобы легко получить к ним доступ, вы можете перебирать свои объекты 3 MatchInfo (всего три совпадения).

$selections.Matches | Foreach-Object {
    $_.Groups[0] # Each full regex match
    $_.Groups[1] # Capture group 1: (abc)
    $_.Groups[2] # Capture group 2: (.*?)
    $_.Groups[3] # Capture group 3: (--- End ---)
}
0 голосов
/ 06 октября 2019

Если все, что вам нужно, это разбить файл на массив из 4-х строчных блоков, то это сделает работу. для чтения файла группами строк используется параметр -ReadCount, равный Get-Content.

это предполагает, что ваши куски всегда 4 строки, хотя. [ ухмылка ]

@'
abc
content_1
content_1b
--- End ---
def
content_2
content_2b
--- End ---
ghi
content_3
content_3b
--- End ---
'@ | Set-Content 'C:\Temp\StevL.txt'

$InStuff = Get-Content -LiteralPath C:\Temp\StevL.txt -ReadCount 4


$InStuff[0]

вывод ...

abc
content_1
content_1b
--- End ---
0 голосов
/ 06 октября 2019

Я предполагаю, что, возможно,

(?i)[\s\S]*?(?:.*---\s*end\s*---\s*)

или

(?i)[\s\S]*?.*---\s*end\s*---\s*

могут быть в порядке, чтобы рассмотреть.


Если вы хотите упростить/ изменить / изучить выражение, это было объяснено на верхней правой панели regex101.com . Если хотите, вы также можете посмотреть в эту ссылку , как она будет сопоставляться с некоторыми примерами ввода.


...