使用流水线将字符串拆分为多维数组

时间:2018-06-08 14:51:26

标签: arrays powershell

考虑以下字符串:

$foo = @"
cfa7b63c88ed1eb7443daeb12128084f17e1ac80
85e59563f059ecf45c104bef1eac9d70c22150ed
e207411bdb392a2d99719c221c8dd59e0dbebe26
df61cb22643321198656bfa7061c4e415eefdfef
3611ed35610793e814c8aa25715aa582ec08a8b6
089dfe7ceb9a0845342a9637527de65245ba297f qwerty
17570cc9387755367db0fc1c5c5f4757db7fd9b3 asdfgh
82a1be2b77e949cb45581c4d25bf962f77041846 uiop
0b726925f60c17795d4655f8ee37d51a3de70b87 lkjjh
7ed66867332bf06486117189701278cdabd31da6 zxcv
"@

我想将其拆分为数组数组,以使输出如下所示:

[0] => [ "089dfe7ceb9a0845342a9637527de65245ba297f", "qwerty" ]
...
[4] => [ "7ed66867332bf06486117189701278cdabd31da6", "zxcv" ]

换句话说,一个包含5个元素的数组,每个元素都是一个2元素数组。请注意,必须排除缺少第二部分的行(即散列后没有任何内容)。

到目前为止,我已经得到了这个:

$bar = $foo -split "`r?`n" |?{ $_.length -gt 40 } |%{ $_.split(" ") }

但这导致了10个元素的一维数组。

获得更多收益:

$bar = $foo -split "`r?`n" |?{ $_.length -gt 40 } |select { $_.split(" ") }

它给了我一个5的数组,但是该数组中的项目是PSCustomObject,其中NoteProperty名为$_.split(" "),它本身就是一个包含2个字符串的数组。如此接近,但到目前为止 - 如果我可以让NoteProperty我做生意了!

考虑到这些限制,是否有可能实现我的目标:

  • 一切都必须通过流水线完成
  • 没有明确命名哈希表元素,等等 - 我想要

如果这是不可能的,或者有些事情我从根本上误解了Powershell及其管道的运作方式(我非常怀疑这种情况),请教育我!

2 个答案:

答案 0 :(得分:5)

如果要在管道中放置一个数组并阻止PowerShell将它们作为单独的管道项删除,则需要通过在数组对象前放置一个逗号来强制它到.Net数组列表:

PS C:\> $bar = $foo -split "`r?`n" | %{ ,$_.split(" ", 2) }
PS C:\> $bar[7]
82a1be2b77e949cb45581c4d25bf962f77041846
uiop
PS C:\> $bar[7][1]
uiop

答案 1 :(得分:1)

这有点笨重,但我认为它符合您的要求:

args, _ = parser.parse_known_args()

输出是一个数组数组(每个数组都有一个来自$foo = @" cfa7b63c88ed1eb7443daeb12128084f17e1ac80 85e59563f059ecf45c104bef1eac9d70c22150ed e207411bdb392a2d99719c221c8dd59e0dbebe26 df61cb22643321198656bfa7061c4e415eefdfef 3611ed35610793e814c8aa25715aa582ec08a8b6 089dfe7ceb9a0845342a9637527de65245ba297f qwerty 17570cc9387755367db0fc1c5c5f4757db7fd9b3 asdfgh 82a1be2b77e949cb45581c4d25bf962f77041846 uiop 0b726925f60c17795d4655f8ee37d51a3de70b87 lkjjh 7ed66867332bf06486117189701278cdabd31da6 zxcv "@ $foo | ForEach-Object {$array = New-Object System.Collections.ArrayList}{ $match = [Regex]::Match($foo, "(?<code1>\w+) (?<code2>\w+)") while($match.Success) { $array.Add(@($match.Groups["code1"].Value, $match.Groups["code2"].Value)) | Out-Null $match = $match.NextMatch() } }{$array} 的匹配行),您可以将管道标记到最后一个括号并继续处理。