2011-12-11 107 views
4

我试图从一些(大)文本文件中提取一组数据。基本上,每一行看起来是这样的:获取powershell正则表达式捕获到表

2011-12-09 18:20:55, ABC.EXE[3b78], The rest of the line... 

我想获得的日期和括号之间的位(进程ID),然后编译的表。第二阶段的任务是对这个表进行分组,这样我就可以得到每个进程id的最早日期,实际上给了我每个进程id的第一个日志条目的日期和时间,它有望接近该实例的开始时间的过程。

到目前为止我有什么(拆分到不同的行可读性)

gci -filter *.log -r 
| select-string '(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}), ABC.EXE\[(.{4})' 
| % { $_.matches } | % { $_.groups } | % { $_.value } 

吐出的捕获。我想忽略第一个捕获,并将第二个和第三个结合到同一行。

帮助? 请问?

编辑: DOH!无法回答我自己的问题。所以...

好的,我想我是在正确的轨道上。一个SO质疑here帮我弄的各个部分,我想,即:

$_.matches[0].groups[1].value, $_.matches[0].groups[2].value 

然后,MSDN文章here展示了如何“丛”中的位为对象,这使得它能够被分组/排序/操纵。最终结果

gci -filter *.log | select-string '(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}), ABC.EXE\[(.{4})' 
| % { new-object object 
    | add-member NoteProperty Name $_.matches[0].groups[1].value -passthru 
    | add-member NoteProperty PId $_.matches[0].groups[2].value -passthru } 

相当混乱,因此,如果有人知道的更清洁的方式做到这一点,请让我知道。

回答

4

其中New-Object cmdlet支持接收性能的哈希表中的参数-Property您可以创建新的对象在PowerShell中V2简单:

New-Object PSObject -Property @{ 
    Name = $_.matches[0].groups[1].value 
    PId = $_.matches[0].groups[2].value 
} 

一般来说,我会做处理有点不同,虽然:

# prepare table 
$data = $(switch -Regex -File filename { 
    '^[^,]+' { $date = [datetime]$Matches[0] } 
    '(?<=\[)[^\]]+' { $id = $Matches[0] } 
    '$' { New-Object PSObject -Property @{ 
     Date = $date 
     PId = $id 
    } } 
}) 

使用switch -regex已经成为一个很好的方式(至少对我来说)为文本数据进行快速和肮脏的解析器。使用-Regex,所有匹配的案例都将运行,在这种情况下全部匹配(所以这只是将匹配的不同部分分开的便利)。第一个抓取日期和时间并将其存储在变量中(甚至作为DateTime值);第二个获得进程ID,第三个匹配在一行的末尾,将它们放在一起。

只是个人的喜好,虽然;我其实从来没有用过Select-String

$data | 
    group PId | 
    foreach { New-Object PSObject -Property @{ 
     PId = $_.Name 
     MinDate = @($_.Group | sort Date)[0].Date 
    } } 

这随后通过进程ID使用刚编译的数据,组,并输出具有用于每个最小日期的ID。

请注意,这更像是一种“看起来不错的代码”方法。如果你正在处理的文件是真的是大,你可能想要更有效的方法。

+0

太棒了,那就是我想要的东西!我从来没有遇到Powershell中的switch语句。我喜欢 –

+0

你可以做一个'Get-Help about_switch'。它非常灵活。 – Joey

+0

+1用于New-Object上的-Property开关。 –