Синтаксический анализ текста в Powershell: определение целевой строки и анализ следующих X строк для создания объектов. - PullRequest
2 голосов
/ 04 февраля 2012

Я анализирую текстовый вывод из дискового массива, который перечисляет информацию о снимках 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, а затем добавить новый объект в коллекцию.

Что я могу изобразитьВыход, как только я идентифицирую первую строку в блоке из четырех строк, как обработать текст из строк второй, третьей и четвертой.Я перебираю каждую строку, нахожу начало блока и затем обрабатываю его.Вот что у меня есть, с комментариями, где волшебство идет:

$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
        }
}

Я искал Google и StackOverflow, пытаясь выяснить, как я могу ссылаться на номер строки объекта, через который я перебираюи я не могу понять это.Я могу слишком полагаться на циклы foreach, так что это влияет на мое мышление, я не знаю.

Ответы [ 4 ]

4 голосов
/ 04 февраля 2012

Как вы говорите, я думаю, что вы слишком много думаете 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" ... опасности нет, всего несколько потраченных впустую циклов.

0 голосов
/ 29 января 2017

попробуйте

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
    }
}
0 голосов
/ 05 февраля 2012
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]
  }
 }
}
0 голосов
/ 04 февраля 2012

Другая возможность

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...