解析/拆分文本数组

时间:2016-05-11 20:20:11

标签: regex powershell split

我有一个原生CMD命令输出这个文本:每个部分用'-----'划线,我希望得到不同数组中的每个部分,所以我可以处理每个部分的结果,

Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.

---Processing--------------------------
---------------------------------------
SKU ID: 2b88c4f2-ea8f-43cd-805e-4d41346e18a7
LICENSE NAME: Office 15, OfficeProPlusVL_MAK edition
LICENSE DESCRIPTION: Office 15, RETAIL(MAK) channel
BETA EXPIRATION: 01/01/1601
LICENSE STATUS:  ---LICENSED--- 
Last 5 characters of installed product key: HT7T7
---------------------------------------
SKU ID: 3e4294dd-a765-49bc-8dbd-cf8b62a4bd3d
LICENSE NAME: Office 15, OfficeVisioProVL_MAK edition
LICENSE DESCRIPTION: Office 15, RETAIL(MAK) channel
BETA EXPIRATION: 01/01/1601
LICENSE STATUS:  ---LICENSED--- 
Last 5 characters of installed product key: WTWRR
---------------------------------------
SKU ID: ed34dc89-1c27-4ecd-8b2f-63d0f4cedc32
LICENSE NAME: Office 15, OfficeProjectProVL_MAK edition
LICENSE DESCRIPTION: Office 15, RETAIL(MAK) channel
BETA EXPIRATION: 01/01/1601
LICENSE STATUS:  ---LICENSED--- 
Last 5 characters of installed product key: TVGWY
---------------------------------------
---------------------------------------
---Exiting-----------------------------

修改 这是我的代码,我认为它很复杂,但只是为了让你知道我不希望你这样做:

Function Parse-OSPPResult
{
Param(
[Parameter(Mandatory = $true)]
$Result
)

$c = $Result | ? {$_ -notmatch '^Microsoft|^Copyright|Processing|Exiting|^LICENSE STATUS'}
$c = $c[0..($c.Length -3)]
$LineNumbers = $c | Select-String '^--' |select -ExpandProperty linenumber

if ($LineNumbers.Count -gt 1)
{
    $array = @{}

    for ($i=0; $i -lt ($LineNumbers.Count -1); $i++)
    {
    $array[$i] = $c[$LineNumbers[$i]..($LineNumbers[($i + 1)]-2)]
    }
    $array[$i] = $c[$LineNumbers[$i]..($c.Length -1)]
}
    else
    {
    $array[0] = $c[$LineNumbers..($c.Length)]
    }

$arr = @()

    foreach ($item in ($array.GetEnumerator() | % {$_.Name}))
    {
    $Name = (($array[$item] | ? {$_ -match '^LICENSE NAME:'}) -split ': ')[-1]
    $Desc = (($array[$item] | ? {$_ -match '^LICENSE DESCRIPTION:'}) -split ': ')[-1]
    $Key = (($array[$item] | ? {$_ -match '^Last 5'}) -split ': ')[-1]
    $row = "" | Select Name,Description,Key
    $row.Name = $Name
    $row.Description = $Desc
    $row.Key = $Key
    $arr += $row
    }

    return $arr
}

结果:

Name                                      Description                    Key  
----                                      -----------                    ---  
Office 15, OfficeProjectProVL_MAK edition Office 15, RETAIL(MAK) channel HT7T7
Office 15, OfficeVisioProVL_MAK edition   Office 15, RETAIL(MAK) channel WTWRR
Office 15, OfficeProPlusVL_MAK edition    Office 15, RETAIL(MAK) channel TVGWY
如果可能,

很乐意看到其他方法。

*注意:有时结果只有一部分......

感谢。

3 个答案:

答案 0 :(得分:4)

我这样做:

function Split-CommandOutput
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string[]]$InputObject
    )

    End
    {
        # Collect all pipeline input and make sure it's an array of strings
        $InputObject = @($input) | ForEach-Object {$_ -split [System.Environment]::NewLine}

        # Separator to split records
        $Separator = '^-+$'

        # Find start and end indexes of each record
        $RecordBounds = 0..($InputObject.Length-1) | Where-Object {$InputObject[$_] -match $Separator}

        # Split records into multidimensional array
        $Records = @()
        for ($i=0 ; $i -lt ($RecordBounds.Length-1) ; $i++)
        {
            $Records += ,($InputObject[($RecordBounds[$i]+1)..($RecordBounds[$i+1]-1)])
        }

        # Process each record
        foreach($record in $Records)
        {
            # For each item in record
            $Properties = @{}
            foreach($item in $record)    
            {
                # Extract data using regex
                if($item -match '\s*(.+)\s*:\s*(.+)\s*')
                {
                    $Properties.Add($Matches[1], $Matches[2])
                }
            }

            # Create new object
            New-Object -TypeName PSCustomObject -Property $Properties
        }
    }
}

您可以将字符串,字符串数组和工具输出直接传递给此函数:

MyTool.exe | Split-CommandOutput
$ArrayOfStrings | Split-CommandOutput
$SingleString | Split-CommandOutput

结果:

LICENSE NAME                               : Office 15, OfficeProPlusVL_MAK edition
LICENSE DESCRIPTION                        : Office 15, RETAIL(MAK) channel
BETA EXPIRATION                            : 01/01/1601
SKU ID                                     : xxxxxxx-ea8f-43cd-805e-xxxxxxxxxx
LICENSE STATUS                             : ---LICENSED--- 
Last 5 characters of installed product key : XXXXX

LICENSE NAME                               : Office 15, OfficeVisioProVL_MAK edition
LICENSE DESCRIPTION                        : Office 15, RETAIL(MAK) channel
BETA EXPIRATION                            : 01/01/1601
SKU ID                                     : xxxxxxx-a765-49bc-8dbd-xxxxxxxxxx
LICENSE STATUS                             : ---LICENSED--- 
Last 5 characters of installed product key : XXXXX

LICENSE NAME                               : Office 15, OfficeProjectProVL_MAK edition
LICENSE DESCRIPTION                        : Office 15, RETAIL(MAK) channel
BETA EXPIRATION                            : 01/01/1601
SKU ID                                     : ed34dc89-1c27-4ecd-8b2f-63d0f4cedc32
LICENSE STATUS                             : ---LICENSED--- 
Last 5 characters of installed product key : XXXXX

答案 1 :(得分:3)

这对我有用

$text = @'
---Processing--------------------------
---------------------------------------
SKU ID: xxxxxxx-ea8f-43cd-805e-xxxxxxxxxx
LICENSE NAME: Office 15, OfficeProPlusVL_MAK edition
LICENSE DESCRIPTION: Office 15, RETAIL(MAK) channel
BETA EXPIRATION: 01/01/1601
LICENSE STATUS:  ---LICENSED--- 
Last 5 characters of installed product key: XXXXX
---------------------------------------
SKU ID: xxxxxxx-a765-49bc-8dbd-xxxxxxxxxx
LICENSE NAME: Office 15, OfficeVisioProVL_MAK edition
LICENSE DESCRIPTION: Office 15, RETAIL(MAK) channel
BETA EXPIRATION: 01/01/1601
LICENSE STATUS:  ---LICENSED--- 
Last 5 characters of installed product key: XXXXX
---------------------------------------
SKU ID: ed34dc89-1c27-4ecd-8b2f-63d0f4cedc32
LICENSE NAME: Office 15, OfficeProjectProVL_MAK edition
LICENSE DESCRIPTION: Office 15, RETAIL(MAK) channel
BETA EXPIRATION: 01/01/1601
LICENSE STATUS:  ---LICENSED--- 
Last 5 characters of installed product key: XXXXX
---------------------------------------
---------------------------------------
---Exiting-----------------------------
'@ -split "`n"

$hash = @{}
$object = foreach ($line in $text) {
    if ($line.startswith('----') -and [bool]$($hash.Keys)) {
        [pscustomobject]$hash
        $hash = @{}
        continue
    } elseif ($line -match '(.*):(.*)') {
        $hash.Add($Matches[1].trim(), $Matches[2].trim())
    }
}

$object

答案 2 :(得分:3)

更整洁的版本:

# Somewhere to hold the information for each program entry
$program = @{}

$result = foreach ($line in Get-Content d:\t.txt) {

    # Reset at the beginning of a new SKU or at the end of everything.
    # Output the program details, and initialize for the next one
    if ($line -match '^SKU' -or $line -match '---Exiting') {
        if ($program.Count) { [pscustomobject]$program }
        $program = @{}
    }


    # Lines which have colons contain data
    if ($line -match ':') {
        $name, $value = $line.Split(':', 2)

        # Replace the long names with the desired shorter names
        switch -Regex ($name) {
            'license name'        { $name = 'Name' }
            'license description' { $name = 'Description' }
            'product key'         { $name = 'Key' }   
        }

        # Save the data for each line into the program store
        $program[$name] = $value
    }

}

# Choose the desired results
$result | select Name, Description, Key

高尔夫版:

(gc d:\t.txt -Raw)-split'-{39}'|%{$p=@{};($_-split'\n')-match':'|%{
$k,$v=$_.Split(':',2);$p[$k]=$v.Trim()};if($p.Count){[pscustomobject]$p}}