PowerShell:从字符串中提取 table

PowerShell: Pull table from a string

我在 PowerShell 2.0 上 运行 有一个命令,输出如下。

上面屏幕截图中的所有内容都是一个巨大的字符串。我想提取字符串的 table 部分,以便我可以将其格式化为列表。最终,我想输出如下:

INSTANCE_NAME: Sample Name
STATUS: MOUNTED
DATABASE_STATUS: ACTIVE

我的第一个想法是使用正则表达式来提取 table。我认为这样的事情可能会奏效,但到目前为止我还没有成功。

$tabletext = [regex]::match($rawtext, "(INSTANCE_NAME(.+\r\n)+)")

编辑: 这是字符串形式的文本。

SQL*Plus: Release 12.1.0.1.0 Production on Wed Apr 20 16:34:57 2016

Copyright (c) 1982, 2013, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

SQL>
INSTANCE_NAME    STATUS       DATABASE_STATUS
---------------- ------------ -----------------
sample_name     OPEN         ACTIVE

SQL> Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

我做了一些非常类似于解析 Firebird sql 输出的事情。

这是一个适用于您的样本数据的脚本:

function parse-headers($lines) {
   $h = $lines[0]

    $headers = $h.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)
    $headers = $headers | %  { 
        new-object pscustomobject -property @{ 
            Length = $_.Length
            Offset = $h.IndexOf($_) 
            Text = $_ 
            }
    }     
    for($i = 1; $i -lt $headers.length; $i++) {
        $headers[$i-1].Length = $headers[$i].Offset - $headers[$i-1].Offset - 1
    }
    $headers[$header.length-1].Length = $h.length - $headers[$header.length-1].Offset

    return $headers
}

function parse-sqloutput($lines) {
    $headers = parse-headers $lines
    $result = @()

    for($l = 2; $l -lt $lines.Length; $l++) {
        $line = $lines[$l]
        $headernames = $headers | % { $h = @{} } { $h[$_.Text] = $null } { $h }
        $r = New-Object -type pscustomobject -Property $headernames
        for($i = 0; $i -lt $headers.length; $i++) {
            try {
                $h = $headers[$i]
                $name = $h.text
                if ($i -eq $headers.length - 1) {
                    $value = $line.Substring($h.Offset).Trim()
                }
                else {
                    $value = $line.Substring($h.Offset, $h.Length).Trim()
                }
                $r.$name = $value
            } catch {
                Write-Warning "failed to parse line $l col $i"
                throw    
            }
        }
        $result += $r
    }
    return $result
}

function get-sqltable($sqlout) {

    #find sql table output
    $startidx = -1
    $endidx = -1

    for($i = 0; $i -lt $sqlout.Length; $i++) {
        $line = $sqlout[$i]
        if ($line -match "^\s*([\-]+\s*)+$") { 
            $startidx = $i - 1 
        }
        if ($startidx -ge 0 -and $line -match "^\s*$") { 
            $endidx = $i 
        }
        if ($startidx -ge 0 -and $endidx -ge 0) { break }
    }

    $sqlout = $sqlout | select -Skip $startidx -First ($endidx-$startidx)
    return $sqlout
}

$sqlout = get-content "sqlout.txt" | out-string 

#split giant string into lines
$sqlout = $sqlout | Split-String "`r`n"
$sqlout = get-sqltable $sqlout

#we should now have only sql table in $sqlout
$result = parse-sqloutput $sqlout

$result | Format-List

想法是:

  1. 找到仅包含 - 个字符的字符串的行,并假设它标记了 header 行。
  2. 寻找 header 行后的第一个空行,并假设它是 table 输出的末尾。
  3. 解析 header 行,获取列的名称和长度。
  4. 根据解析的列长度获取值。