Powershell中的文本解析:识别目标线并解析下一个X线以创建对象

时间:2012-02-03 23:41:36

标签: parsing powershell

我正在解析磁盘阵列的文本输出,该阵列以可预测的格式列出有关LUN快照的信息。在尝试以其他方式以可用的方式从数组中获取此数据之后,我唯一能做的就是生成此文本文件并解析它。输出如下:

SnapView logical unit name:  deleted_for_security_reasons
SnapView logical unit ID:  60:06:01:60:52:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Target Logical Unit:  291
State:  Inactive

这会在文件中重复所有文件,每组之间有一个换行符。我想识别一个组,解析四行中的每一行,创建一个新的PSObject,将每行的值添加为新的NoteProperty,然后将新对象添加到集合中。

我能弄清楚的是,一旦我识别出四行块中的第一行,如何处理第2,3和4行的文本。我循环遍历每一行,找到块的开始,然后处理它。这就是我到目前为止所做的评论以及魔术的评论:

$snaps = get-content C:\powershell\snaplist.txt
$snapObjects = @()

foreach ($line in $snaps)
    {

        if ([regex]::ismatch($line,"SnapView logical unit name"))
        {
            $snapObject = new-object system.Management.Automation.PSObject
            $snapObject | add-member -membertype noteproperty -name "SnapName" -value $line.replace("SnapView logical unit name:  ","")
            #Go to the next line and add the UID
            #Go to the next line and add the TLU
            #Go to the next line and add the State
            $snapObjects += $snapObject
        }
}

我已经搜索过谷歌和StackOverflow试图找出我如何引用我正在迭代的对象的行号,我无法弄明白。我可能过多依赖foreach循环,所以这影响了我的想法,我不知道。

4 个答案:

答案 0 :(得分:4)

正如你所说,当你想要 时,我认为你在想太多 foreach 。以下修改应该更符合您的要求:

$snaps = get-content C:\powershell\snaplist.txt
$snapObjects = @()

for ($i = 0; $i -lt $snaps.length; $i++)
    {
        if ([regex]::ismatch($snaps[$i],"SnapView logical unit name"))
        {
            $snapObject = new-object system.Management.Automation.PSObject
            $snapObject | add-member -membertype noteproperty -name "SnapName" -value ($snaps[$i]).replace("SnapView logical unit name:  ","")
            # $snaps[$i+1] Go to the next line and add the UID
            # $snaps[$i+2] Go to the next line and add the TLU
            # $snaps[$i+3] Go to the next line and add the State
            $snapObjects += $snapObject
        }
}

while循环可能更干净,因为当你遇到这种情况时你可以将$ i增加4而不是1,但由于其他3行不会触发“if”语句......没有危险,只是浪费了几个周期。

答案 1 :(得分:0)

另一种可能性

function Get-Data {
    $foreach.MoveNext() | Out-Null
    $null, $returnValue = $foreach.Current.Split(":")

    $returnValue
}

foreach($line in (Get-Content "C:\test.dat")) {

    if($line -match "SnapView logical unit name") {
        $null, $Name = $line.Split(":")
        $ID    = Get-Data
        $Unit  = Get-Data
        $State = Get-Data

        New-Object PSObject -Property @{
            Name  = $Name.Trim()
            ID    = ($ID -join ":").Trim()
            Unit  = $Unit.Trim()
            State = $State.Trim()
        }
    }
}

Name                         ID                                              Unit State   
----                         --                                              ---- -----   
deleted_for_security_reasons 60:06:01:60:52:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX 291  Inactive

答案 2 :(得分:0)

switch -regex -file C:\powershell\snaplist.txt {
 '^.+me:\s+(\S*)' {$SnapName = $Matches[1]}
 '^.+ID:\s+(\S*)' {$UID = $Matches[1]}
 '^.+it:\s+(\S*)' {$TLU = $Matches[1]}
 '^.+te:\s+(\S*)' {
  New-Object PSObject -Property @{
   SnapName = $SnapName
   UID = $UID
   TLU = $TLU
   State = $Matches[1]
  }
 }
}

答案 3 :(得分:0)

试试这个

Get-Content "c:\temp\test.txt" | ConvertFrom-String -Delimiter ":  " -PropertyNames Intitule, Value

如果你有多个数据包试试这个

$template=@"
{Data:SnapView logical unit name:  {UnitName:reasons}
SnapView logical unit ID:  {UnitId:12:3456:Zz}
Target Logical Unit:  {Target:123456789}
State:  {State:A State}}
"@


Get-Content "c:\temp\test.txt" | ConvertFrom-String -TemplateContent $template | % {
    [pscustomobject]@{
    UnitName=$_.Data.UnitName
    UnitId=$_.Data.UnitId
    Target=$_.Data.Target
    State=$_.Data.State
    }
}