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
想法是:
- 找到仅包含
-
个字符的字符串的行,并假设它标记了 header 行。
- 寻找 header 行后的第一个空行,并假设它是 table 输出的末尾。
- 解析 header 行,获取列的名称和长度。
- 根据解析的列长度获取值。
我在 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
想法是:
- 找到仅包含
-
个字符的字符串的行,并假设它标记了 header 行。 - 寻找 header 行后的第一个空行,并假设它是 table 输出的末尾。
- 解析 header 行,获取列的名称和长度。
- 根据解析的列长度获取值。