如何在文本文件中存储哈希表数组,然后在每个哈希表

时间:2016-10-16 19:24:35

标签: powershell hashtable

我正在使用文本文件作为我正在开发的应用程序的后端。我首先开始将文本文件保留为人类可读的格式,但我认为没有任何意义,最好不要格式化。

我现在在后端开发过程中创建一个具有相同键但每个条目的值不同的单行哈希表。似乎合乎逻辑且易于使用。

以下是文本文件中条目的模型:

@{'bName'='1xx'; 'bTotal'='1yy'; 'bSet'='1zz'}
@{'bName'='2xx'; 'bTotal'='2yy'; 'bSet'='2zz'}
@{'bName'='3xx'; 'bTotal'='3yy'; 'bSet'='3zz'}

正如您所看到的,每个条目的键都相同,但值会有所不同。 (值的数字和重复性质纯粹是巧合的,并且为了模型而设置。实际值不是数字导向的,并且不会像示例中所见那样重复。

我可以通过输入以下内容来访问键和值:

$hash = Get-Content .\Desktop\Test.txt | Out-String | iex

输出:

Name                    Value
----                    -----
bName                   1xx
bTotal                  1yy
bSet                    1zz
bName                   2xx
bTotal                  2yy
bSet                    2zz
bName                   3xx
bTotal                  3yy
bSet                    3zz

我最终想要做的是收集bNamebTotalbSet的每个值,以便我可以将每个值附加到单独的WinForms ComboBox。 WinForms部分很简单,我只是在从文本文件中的每个哈希表中获取值时遇到一些问题。

我试过了:

$hash.Values | ?{$hash.Keys -contains 'bName'}

但无论管道中给出的$hash.Value匹配如何,它都会打印出每$hash.Key个。{/ p>

我知道$hash是一个数组,我想我可能必须在foreach ($hash | %{})循环中管理每次迭代,但我不太确定正确的方法。例如,当我尝试:

$hash | $_.Keys

$hash | $_.Values

它并不像哈希表一样对待每次迭代。

我在这里做错了什么?我是否会以复杂的方式解决这个问题,而有更简单的方法可以实现这一目标?我愿意接受各种各样的想法或建议。

作为事后的想法:当你离开并将注意力转移到别的东西时,一个明显的解决方案经常会出现这种情况,这很有趣。

我去吃午饭,我不能,为了我的生活,我开始理解为什么我没有意识到我可以很容易地做到这一点:

$hash.bName

或:

$hash.bTotal

或:

$hash.bSet

这将完全按照我的意愿行事。但是,考虑到所提供的答案,我可能会使用CSV格式的.ini文件,而不是创建一个哈希表数组。

2 个答案:

答案 0 :(得分:1)

PowerShell内置了csv处理功能,因此在这种情况下使用它是一个不错的选择。因此,假设您将数据存储在标准csv格式的文件中,并带有标题:

"bName","bTotal","bSet"
"1xx","1yy","1zz"
"2xx","2yy","2zz"
"3xx","3yy","3zz"

然后你导入你的数据:

$data = Import-Csv $path

现在您有一个PsCustomObject数组,csv文件中的每个标头都是该对象的属性。因此,例如,如果您想获得第二个对象的bTotal,则可以执行以下操作:

$data[1].bTotal
  

2yy

答案 1 :(得分:1)

将哈希表存储在文本文件中的一种方法是INI format

[hashtable1]
bName=1xx
bTotal=1yy
bSet=1zz

[hashtable2]
bName=2xx
bTotal=2yy
bSet=2zz

[hashtable3]
bName=3xx
bTotal=3yy
bSet=3zz

INI文件基本上是文本形式的哈希表的哈希表。可以阅读like this

$ht = @{}
Get-Content 'C:\path\to\hashtables.txt' | ForEach-Object {
  $_.Trim()
} | Where-Object {
  $_ -notmatch '^(;|$)'
} | ForEach-Object {
  if ($_ -match '^\[.*\]$') {
    $section = $_ -replace '\[|\]'
    $ht[$section] = @{}
  } else {
    $key, $value = $_ -split '\s*=\s*', 2
    $ht[$section][$key] = $value
  }
}

并且写得像这样:

$ht.Keys | ForEach-Object {
  '[{0}]' -f $_
  foreach ($key in $ht[$_].Keys) {
    '{0}={1}' -f $key, $ht[$_][$key]
  }
} | Set-Content 'C:\path\to\hashtables.txt'

哈希表的哈希表中的单个值可以这样访问:

$ht['section']['key']

或者像这样:

$ht.section.key

另一种选择是将每个哈希表存储在单独的文件中

hashtable1.txt

bName=1xx
bTotal=1yy
bSet=1zz

hashtable2.txt

bName=2xx
bTotal=2yy
bSet=2zz

hashtable3.txt

bName=3xx
bTotal=3yy
bSet=3zz

这样您就可以通过ConvertFrom-StringData将每个文件导入哈希表:

$ht1 = Get-Content 'C:\path\to\hashtable1.txt' | Out-String |
       ConvertFrom-Stringdata

编写文件基本上与上面相同(没有ConverTo-StringData cmdlet):

$ht1.Keys | ForEach-Object {
  '{0}={1}' -f $_, $ht[$_]
} | Set-Content 'C:\path\to\hashtables1.txt'