2013-08-06 66 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

相關問題