【发布时间】:2013-08-06 19:43:06
【问题描述】:
全部!
我正在编写将标准 INI 文件结构转换为基于哈希表和数组的代码。例如下图的INI sn-p:
[Book]
title="Moby Dick"
author="Herman Melville"
genre=fiction
genre=fantasy
[Book]
title="James and the Giant Peach"
author="Roald Dahl"
genre="fiction"
看起来像:
@{
"Book" = [
@{
"title" = ["Moby Dick"];
"author" = ["Herman Melville"];
"genre" = ["fiction","fantasy"]
},
@{
"title" = ["James and the Giant Peach"];
"author" = ["Roald Dahl"];
"genre" = ["fiction"]
}
]
}
我想说明具有多个同名节和具有多个同名属性的节的 INI 文件,因此是这种数据结构。我知道我可以使用一棵树来做同样的事情,但我不太关心它的速度,而且在我编写它的时候这更容易实现。
这是通过更新一个哈希表来完成的,该哈希表将一个部分中的所有属性与其值相关联(我们称之为$items),然后更新将每个部分与上述哈希表相关联的主哈希表(我们称之为$results )。哈希表是全局的,属性哈希表在迭代到新部分时会被清除。
虽然我编写的代码可以做到这一点并且运行良好,但几分钟后我对 Powershell 清除哈希表的方式感到困惑。如果我使用$items.Clear() 清除$items,与$results 中的所有元素关联的哈希表也会被清除。 但是,如果我通过声明$items=@{} “清除”它,则不会发生这种情况.
我假设发生这种情况是因为前一种情况下的哈希表都是对全局哈希表的引用,并且在后一种情况下是独立的对象。这是怎么回事?
代码如下;抱歉,如果其中任何一个令人困惑(并且它不是典型的 Powershell 语法)。将$items = @{} 替换为$items = $items.Clear() 进行复制:
function parse ($file) {
$result = @{}
if (!(Test-Path $file)) {
write-host "File does not exist: $file"
} elseif (!($data = cat $file)) {
write-host "File has no data: $file"
} else {
$last_value = ""
$last_data = ""
$items = @{}
foreach ($line_raw in $data | ?{$_.Trim().Length -gt 0}) {
$line = $line_raw.TrimStart().TrimEnd()
$first_char = $line[0]
switch ($first_char) {
';' {
continue
}
'[' {
$key = $line -replace "\[|\]",""
if ($last_key) {
if (!($result.ContainsKey($last_key)))
{ $result.Add($last_key,@($items)) }
else
{ $result[$last_key] += $items }
if ($last_key -ne $key)
{ $items = @{} }
}
$last_key = $key
}
default {
$item , $data = $(
$sep = $line.indexOf('=')
$line.substring(0,$sep) , $line.substring($sep+1)
)
if (!$items.ContainsKey($item))
{ $items.Add($item,@($data)) }
else
{ $items[$item] += $data }
}
}
}
$result
}
}
【问题讨论】:
-
我似乎无法复制这种行为。您能否发布有关如何设置不同哈希表的代码?
标签: .net powershell