PowerShell中的多行正则表达式匹配

时间:2015-06-10 15:04:26

标签: regex 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*$))'

如何使模式匹配跨多行工作?

1 个答案:

答案 0 :(得分:0)

使用您在帖子中测试数据完全我使用Select-StringConvertFrom-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('"','')去掉变量引号。我认为这是次要的,但最终的标题有领先的s,这可能不是什么大问题。

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对象做的任何事情。