簡體   English   中英

PowerShell 5.1 有人可以解釋哈希表和 splatting

[英]PowerShell 5.1 Can someone please explain hashtable and splatting

鑒於:
PowerShell 5.1

我在理解哈希表和 splatting 時遇到了一些麻煩。 splatting 是使用 hash 表來做的,還是完全不同的東西?

我有以下代碼:

$hashtable1 = @{}       
$hashtable1.add('PROD',@{ FirstName = 'John'; LastName = 'Smith'})

function Main() {
    $sel = $hashtable1['PROD']
    
    Function1 $sel    
    Function2 @sel
}

function Function1([hashtable] $x) {
    "Value: $($x.LastName)"
    $x.FirstName
}

function Function2([string] $firstName) {
    "Value: $($firstName)"
}

Main

在此處輸入圖像描述

Splatting和hashtables在PowerShell中是相關的概念,但它們不是一回事。

哈希表是 PowerShell 中的一種數據結構,可讓您存儲鍵值對。 你可以把它想象成其他編程語言中的字典或關聯數組。 您可以使用 @{} 符號創建哈希表,然后使用 = 運算符添加鍵值對,如下所示:

$hashtable = @{
    "Key1" = "Value1"
    "Key2" = "Value2"
}

另一方面,Splatting 是一種允許您使用 @ 符號將參數值集合傳遞給命令或 function 的技術。 當您在包含哈希表的變量前使用 @ 符號時,PowerShell 會自動將哈希表擴展為其單獨的鍵值對,並將它們作為單獨的 arguments 傳遞給命令或 function。

例如,您可以使用 splatting 調用 function 並將哈希表中的值作為 arguments 傳遞:

function MyFunction([string]$Name, [int]$Age) {
    Write-Host "Name: $Name"
    Write-Host "Age: $Age"
}

$parameters = @{
    "Name" = "John"
    "Age" = 30
}

MyFunction @parameters

這將調用 MyFunction function,分別傳遞值“John”和 30 作為 Name 和 Age arguments。

@postanote 有一些關於哈希表和 splatting 的非常好的鏈接,是很好的讀物。 以您的示例為例,您有兩個不同的功能。 一個將哈希表作為參數處理,第二個只能處理單個字符串參數。 hashtable不能用來給第二個function傳遞參數,eg:

PS C:\> Function2 $sel
Value: System.Collections.Hashtable

從概念上講,使用哈希表和 splatting 之間的真正區別不在於如何使用它們將信息和參數傳遞給函數,而在於函數及其參數如何接收信息

是的,某些函數可以將哈希表和 arrays 作為參數,但是,通常在 98% 的情況下,函數使用哈希表作為命名參數來獲取其值。

對於前。 Copy-Item不使用 hash 表作為參數。 如果是這樣,您是否希望每次復制任何內容時都這樣做:

$hashtable = @{
  Path = "C:\Temp\myfile.txt",
  Destination = "C:\New Folder\"
}
Copy-Item -Parameters $hashtable

不,相反,您希望將參數作為字符串,這樣您就可以使它成為一個更簡單的襯里:

Copy-Item -Path "C:\Temp\myfile.txt" -Destination "C:\New Folder\"

對於大多數人來說,處理單個strings比傳遞一個通用的、大的、哈希表“配置”更有意義。 此外,通過將參數分離為單獨的字符串、整數、浮點數、字符等,也更容易進行驗證、默認值、強制/非強制參數等。

盡管說了這么多,但在某些情況下,您的某些函數有很多參數(例如發送 email 消息),或者您想多次執行某些操作(例如從 CSV 文件復制/移動大量文件)。 在這種情況下,使用哈希表和/或 arrays 和/或 arrays 哈希表會很有用。

這就是 splating 的用武之地。它需要一個哈希表,而不是像傳遞單個值那樣對待它(即為什么Function2 $sel返回System.Collections.Hashtable ), @符號告訴 PowerShell 它是一個值的集合,並使用該集合嘗試匹配 function 的參數。這就是為什么將散列表傳遞給Function2不起作用,但 splatting 起作用的原因,例如:

PS C:\> Function2 @sel
Value: John

在這種情況下,它采用哈希表$sel並通過使用@sel PowerShell 現在知道不按原樣傳遞哈希表,而是打開集合並將$sel.FirstName-Firstname參數匹配。

現有答案中有很好的信息,但讓我嘗試進行重點總結:

您的實際問題的答案是:

  • 是的, @{ FirstName = 'John'; LastName = 'Smith' } @{ FirstName = 'John'; LastName = 'Smith' }也是一個哈希表,即以聲明性哈希表文字的形式 - 就像@{}是一個的哈希表文字(它構造一個最初沒有條目的實例)。

    • 哈希表字面量由零個或多個鍵值對組成,每個鍵與其值之間用=分隔,鍵值對之間用;分隔。 或換行符。
    • 鍵通常不需要引號(例如FirstName ),除非它們包含特殊字符(例如空格)或者它們是通過表達式(例如變量引用)提供的; 有關詳細信息,請參閱此答案
  • 這與稍后編程方式將條目添加到哈希表形成對比,因為您的$hashtable1.Add('PROD', ...)方法調用舉例說明(其中PROD是條目,而...是條目的占位符) .

    • 請注意,使用.Add()方法的一種更方便的替代方法是使用索引表達式甚至點符號(類似屬性的訪問),但請注意,它會根據情況添加條目或更新現有條目: $hashtable1['PROD'] =...$hashtable1.PROD =...

問題標題所暗示的更廣泛問題的答案:

  • PowerShell 的哈希表是一種數據結構,通常稱為字典,或者在其他語言中稱為關聯數組map 具體來說,它們是 .NET [hashtable] ( System.Collections.Hashtable ) 類型的不區分大小寫的實例,它是無序鍵值對條目的集合。 哈希表可以通過關聯的鍵高效地查找值。

    • 通過語法糖[ordered] @{... } ,即通過將[ordered]放在哈希表文字之前,PowerShell 提供了一個不區分大小寫的有序字典,它維護條目定義順序並允許除了通常的位置索引之外的訪問基於密鑰的訪問。 此類有序哈希表是 .NET System.Collections.Specialized.OrderedDictionary類型的不區分大小寫的實例。

      • 一個簡單的例子:

         # Create an ordered hashtable (omit [ordered] for an unordered one). $dict = [ordered] @{ foo = 1; bar = 'two' } # All of the following return 'two' $dict['bar'] # key-based access $dict.bar # ditto, with dot notation (property-like access) $dict[1] # index-based access; the 2nd entry's value.
  • Splatting是一種參數傳遞技術,它可以通過包含編碼 arguments 的數據結構的變量間接傳遞 arguments ,這對於動態構造 arguments 並使調用許多 arguments 更具可讀性很有用。

    • 通常且穩健 - 但僅當調用帶有聲明參數PowerShell命令時- 該數據結構是一個hashtable ,其條目鍵必須與目標命令的參數名稱(例如,鍵Path目標參數-Path )匹配,並且其條目值指定通過。

      • 換句話說:這種形式的 splatting 使用哈希表來實現名為arguments 的傳遞(參數值前面是目標參數的名稱,例如直接參數傳遞中的-Path /foo )。

      • 一個簡單的例子:

         # Define the hashtable of arguments (parameter name-value pairs) # Note that File = $true is equivalent to the -File switch. $argsHash = @{ LiteralPath = 'C:\Windows'; File = $true } # Note the use of "@" instead of "$"; equivalent to: # Get-ChildItem -LiteralPath 'C:\Windows' -File Get-ChildItem @argsHash
    • 或者,數組可用於展開,僅包含參數,然后按位置將其傳遞給目標命令。

      • 換句話說:這種形式的splatting使用數組來實現傳遞位置arguments僅參數值)。

      • 這種形式通常只在以下情況下有用:

        • 調用 PowerShell 腳本或函數時,這些腳本或函數未正式聲明參數並通過自動$args變量訪問它們的 - 總是位置- arguments
        • 調用外部程序時; 請注意,從PowerShell的角度來看,在調用外部程序時沒有named arguments的概念,因為PowerShell對這種情況下的參數語法一無所知,所有arguments只是簡單地一一放在進程命令行中,它取決於目標程序將它們解釋為參數名稱與值。
      • 一個簡單的例子:

         # Define an array of arguments (parameter values) $argsArray = 'foo', 'bar' # Note the use of "@" instead of "$", though due to calling an # *external program* here, you may use "$" as well; equivalent to: # cmd /c echo 'foo' 'bar' cmd /c echo @argsArray

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM