2013-08-06 65 views
2

全部!@ {}和[Hashtable] :: Clear()之间有什么区别?

我正在编写代码将标准INI文件结构转换为基于哈希表和数组的代码。例如,INI代码段如下所示:

[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中的所有元素关联的散列表也会被清除。但是,如果我通过陈述[email protected]{}“清除”它,则不会发生这种情况。

我假设发生这种情况是因为前一种情况下的哈希表都是对全局哈希表的引用,并且是后者中的独立对象。这是怎么回事?

代码在下面;对不起,如果任何这是令人困惑(并且它不是典型的Powershell语法)。与$items = $items.Clear()替换$items = @{}复制:

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 
    } 
} 
+0

我似乎无法复制该行为。你可以发布代码,了解你如何设置不同的哈希表? – DavidN

回答

4

$items的可变是指在这种情况下包含一个哈希表的存储位置。当您为该变量赋值@{}时,您正在将该变量分配给新的空哈希表的引用。如果没有其他引用原始散列表,那么垃圾收集器将回收它的内存。在散列表上执行Clear()方法会导致它重置为空状态。

+0

是的,我想这是发生了什么事。再次感谢基思! 作为一个侧面的问题,这是用Powershell解析INI文件的推荐方式吗?尽管脚本专家的示例使用更简单的代码,但似乎并没有将属性与其值相关联,尽管它将节与其属性相关联。提前致谢! –

0

那么首先,我想你的意思是:$ items.Clear(),而不是$项目= $ items.Clear()

我得仔细看看,因为我不看到任何可疑的东西,但我只是想让你知道,回答一个更基本的问题,上面的所有代码几乎都是通过使用ConvertTo-Json和ConvertFrom-Json cmdlet来完成Powershell中的几行代码。当应用于内存中的哈希表和您正在存储的文件时。给它一个镜头,你会明白我的意思。

+0

谢谢!你说得对,我的意思是'$ items.Clear()。'这是否适用于这种数据的结构?我认为这包含在Powershell v3 +中。 –

+0

是的。看看它如何转换哈希表来回。我认为你可以使用v3,因为我没有看到任何相反的事情。如果不是这种情况,你应该在问题中真正包含这种类型的约束。 – DavidN

相关问题