2015-06-10 3 views
1

Я пытаюсь извлечь определенный блок строк из текстового файла, который содержит что-то вроде этого:Multiline матч регулярного выражения в PowerShell

... 
sCountry = "USA" 
sCity = "New York" 
sState = "New York" 
... 
sCountry = "USA" 
sCity = "Los Angeles" 
sState = "California" 

, где эти три строки повторяется на протяжении текстового файла; Я просто хочу, чтобы извлечь эти строки текста, и положить поля данных в формате CSV, так что у меня есть что-то вроде

"USA","New York","New York" 
"USA","Los Angeles","California" 
... 

До сих пор у меня есть это:

$inputPath = 'C:\folder\file.vbs' 
$outputFile = 'C:\folder\extracted_data.csv' 
$fileContent = [io.file]::ReadAllText($inputPath) 

$regex = '(?sm)(s[A-Z][a-z]+ = "\w*"(\s*$)){3}' 

$fileContent = $fileContent | Select-String $regex -AllMatches | % {$_.Matches} | % {$_.Value} 
$fileContent = [regex]::Replace($fileContent, 'sCountry = ', '') 
$fileContent = [regex]::Replace($fileContent, '(?sm)((^\s*)s[A-Z][a-z]+ =)', ',') 
$fileContent > $outputFile 

который я был в состоянии получите, посмотрев на это:

Multiline regex to match config block.

Однако мой выходной файл пуст, когда я запускаю скрипт. Это не будет шаблон матча с $regex рисунком я представил, но он будет соответствовать на одной строке, если я что-то вроде:

$regex = '(?sm)(sCountry = "\w*"(\s*$))' 

но если я что-то вроде:

$regex = '(?sm)(s[A-Z][a-z]+ = "\w*"(\s*$))' 

Как создать сопоставление шаблонов по нескольким строкам?

+0

Какую версию powershell вы используете? – mjolinor

+0

@mjolinor, Windows PowerShell ISE, 3.0, NOT (x86) – cerremony

ответ

0

Используя вам тестовые данные точно, как у вас в вашем посте я взял другой подход, используя Select-String и ConvertFrom-StringData. У этого есть незначительный недостаток, который можно упустить (или обратиться, если вам действительно нужно). Здесь предостережение состоит в том, что первая строка sCountry должна произойти, а строка sState должна встречаться последним в группе.

$results = ((Get-Content C:\temp\test.txt -Raw) | 
    Select-String -Pattern "(?sm)sCountry.*?sState.*?$" -AllMatches).Matches.Value 
$results | ForEach-Object{ 
    New-Object -TypeName PSCustomObject -Property ($_.Replace('"','') | ConvertFrom-StringData) 
} | Export-CSV -NoTypeInformation C:\temp\output.csv 

Чтобы получить группы данных регулярного выражения здесь будет захватить все, от «sCountry», чтобы затем положить конец строки из которой следующая «sState» происходит. Эта текущая логика потерпит неудачу, если между ними, помимо ожидаемых, будут другие линии. Мы избавляемся от переменных котировок простым .Replace('"',''). Я думаю, что это незначительно, но в результате заголовки имеют ведущие, что, вероятно, не имеет большого значения.

Объект в PowerShell выглядит так, прежде чем он экспортируется в CSV

sCity  sCountry sState  
-----  -------- ------  
New York USA  New York 
Los Angeles USA  California 

Какой будет чистой продукции, как это в формате CSV

"sCity","sCountry","sState" 
"New York","USA","New York" 
"Los Angeles","USA","California" 

Прохладный думаю, вы не могли бы сортировать данные перед его экспортом. Или что-нибудь действительно, что вы могли бы сделать с объектами PowerShell.