PowerShell在运行命令时将输出返回给我:
Mod Ports Module-Type Model Status --- ----- ----------- ------------------ ---------- 1 48 2/4/8/10/16 Gbps Advanced FC Module DS-X9448-768K9 ok 2 48 2/4/8/10/16 Gbps Advanced FC Module DS-X9448-768K9 ok 3 0 Supervisor Module-3 DS-X97-SF1-K9 ha-standby 4 0 Supervisor Module-3 DS-X97-SF1-K9 active *
我在尝试拆分时遇到了麻烦,因为它不是制表符分隔的,而是空格分隔的,因此,当我使用.split("")
时,列Module-Type
的分隔不正确是因为它的内容也有空格。
我是新来的,任何帮助将不胜感激。
这是我的代码:
$RS = .\Plink server@puttysession -pw "password" "command"
foreach ($RSln in $RS){
$arr = $RSln.split('',[System.StringSplitOptions]::RemoveEmptyEntries)
Write-Host $RSln "|" $arr.Length
}
这给了我创建的数组的行和长度,前两行是长度为5的数组,由于ModuleType
答案 0 :(得分:2)
在PowerShell中处理此类输入的推荐方法是将其解析为自定义对象。您可以使用正则表达式来做到这一点:
$RS | Where-Object {
$_ -match '(\d+)\s+(\d+)\s+(.*?)\s+([a-z]+(?:-[a-z0-9]+){2,})\s+(.*)'
} | ForEach-Object {
New-Object -Type PSObject -Property @{
'Mod' = [int]$matches[1]
'Ports' = [int]$matches[2]
'ModuleType' = $matches[3]
'Model' = $matches[4]
'Status' = $matches[5]
}
}
或(如果列的宽度是固定的,则)通过以定义的偏移量提取子字符串来实现:
$RS | Select-Object -Skip 2 | ForEach-Object {
New-Object -Type PSObject -Property @{
'Mod' = [int]$_.Substring(0, 3).Trim()
'Ports' = [int]$_.Substring(5, 5).Trim()
'ModuleType' = $_.Substring(12, 35).Trim()
'Model' = $_.Substring(48, 18).Trim()
'Status' = $_.Substring(67).Trim()
}
}
需要Select-Object -Skip 2
来跳过2个标题行。
如果所有列都被一个以上的空格分隔,则可以通过-split '\s\s+'
分隔(以2个或更多连续的空白字符分隔)。但是,对于您的数据则不是这样,因为至少前2个数据行在第3列和第4列之间只有一个空格。
答案 1 :(得分:0)
大多数PowerShell脚本编写者可能会说,将类似于Format-Table
输出的任何文本表用作输入是个坏主意,但我想挑战一下,因为格式化后的源表可以被人类读取,如果人类可以读取可以阅读并确定关于列的开始和结束位置的布局,程序应该能够执行相同的操作...
在某些情况下(例如,对于StackOverflow网站上的示例数据),它甚至可能比其他格式(如CSV
(难以读取且仅支持字符串数据< / em>),XML
(非常冗长,因此也难以阅读)或JSON
(或PSON
,复杂数据,但不适用于包含简单本机属性的对象列表)
基于这种想法,我编写了一个可重用的ConvertFrom-SourceTable
cmdlet,可以从PowerShell画廊下载该文件,并从GitHub iRon7/ConvertFrom-SourceTable
存储库中获取源代码。
在您的情况下,将表转换为对象的命令就像$RS | ConvertFrom-SourceTable
一样简单,让我展示一下:
$RS = '
Mod Ports Module-Type Model Status
--- ----- ---------------------------------- ------------------ -----------
1 48 2/4/8/10/16 Gbps Advance FC Module DS-X9448-768K9 ok
2 48 2/4/8/10/16 Gbps Advance FC Module DS-X9448-768K9 ok
3 0 Supervisor Module-3 DS-X97-SF1-K9 ha-standby
4 0 Supervisor Module-3 DS-X97-SF1-K9 active *
'
$RS | ConvertFrom-SourceTable
Status : ok
Model : DS-X9448-768K9
Ports : 48
Mod : 1
Module-Type : 2/4/8/10/16 Gbps Advance FC Module
Mod : 2
Module-Type : 2/4/8/10/16 Gbps Advance FC Module
Ports : 48
Model : DS-X9448-768K9
Status : ok
Mod : 3
Module-Type : Supervisor Module-3
Ports : 0
Model : DS-X97-SF1-K9
Status : ha-standby
Mod : 4
Module-Type : Supervisor Module-3
Ports : 0
Model : DS-X97-SF1-K9
Status : active *
由于所有数据都保持左对齐(并且每一列都需要一个标题),因此可以从一开始就确定列的布局,这意味着您甚至可以 stream 该表输入(假设{ {1}}通过管道分别输出每行):
.\Plink
(意思是如果您将源表提供为多行字符串,则.\Plink server@puttysession -pw "password" "command" | ConvertFrom-SourceTable
cmdlet将确定整个表上的列,否则将基于标题,过去和当前记录)
如果源表具有更好的格式约定,例如“非字符串数据(需要解释的数据)右对齐”(实际上由ConvertFrom-SourceTable
完成)。您可以假设(如@Ansgar Wiechers所做的那样)Format-Table
和Mod
是整数是事实。例如:
Ports
(请注意,在此示例中,$Object = ConvertFrom-SourceTable '
Mod Ports Module-Type Model Status
--- ----- ----------- ----- ------
1 48 2/4/8/10/16 Gbps Advance FC Module DS-X9448-768K9 ok
2 48 2/4/8/10/16 Gbps Advance FC Module DS-X9448-768K9 ok
3 0 Supervisor Module-3 DS-X97-SF1-K9 ha-standby
4 0 Supervisor Module-3 DS-X97-SF1-K9 ha-standby
'
将提供与输入相同的输出)
有关更多示例,请使用帮助:$Object | Format-Table