ค้นหาเว็บไซต์

PowerShell HashTable - ทุกสิ่งที่คุณจำเป็นต้องรู้


Hashtables ใน PowerShell สามารถใช้เพื่อจัดเก็บข้อมูลในลักษณะที่มีโครงสร้าง ซึ่งทำได้โดยใช้คู่คีย์/ค่าที่ช่วยให้คุณสามารถดึงข้อมูลที่จำเป็นจากแฮชเทเบิลได้อย่างง่ายดาย คุณสามารถเปรียบเทียบแฮชเทเบิลใน PowerShell กับอาเรย์ที่เชื่อมโยงได้หากต้องการ

Hashtables ถูกใช้ค่อนข้างบ่อยใน PowerShell เนื่องจากเป็นวิธีที่ดีในการจัดเก็บและประมวลผลข้อมูล ข้อดีของ hashtable คือคีย์และค่าสามารถเป็นอ็อบเจกต์ประเภทใดก็ได้ ดังนั้นคุณจึงไม่ได้จำกัดอยู่เพียงจำนวนเต็มและสตริง แต่คุณสามารถสร้างแฮชเทเบิลแบบซ้อนได้ เป็นต้น

ในบทความนี้ เราจะดูแฮชเทเบิลและวิธีใช้ในสคริปต์ PowerShell ของคุณ

Hashtable กับอาร์เรย์

ก่อนที่เราจะดู hashtables ก่อนอื่นเรามาอธิบายความแตกต่างระหว่าง hashtables และ array กันก่อน นี่เป็นคำถามที่มักถูกถาม และผู้คนมักจะสับสนระหว่างทั้งสอง

อาร์เรย์คือรายการค่าที่จัดทำดัชนีไว้ ดัชนีจะถูกสร้างขึ้นโดยอัตโนมัติเมื่อคุณเพิ่มค่าให้กับอาร์เรย์ ดังนั้นคุณไม่สามารถควบคุมตำแหน่งที่คุณจัดเก็บข้อมูลในอาร์เรย์ได้

$array = @('apple','raspberry','kiwi')

เราสามารถเข้าถึงรายการในอาร์เรย์ได้โดยการวนซ้ำหรือเข้าถึงรายการตามหมายเลขดัชนี:

$array | Foreach { Write-Host $_ }

# Result
apple
raspberry
kiwi

# Or by index number
write-host $array[1]

# Result
raspberry

เรายังสามารถเพิ่มหรืออัปเดตค่าในอาร์เรย์ได้ แต่เราไม่สามารถเปลี่ยนแปลงหรือกำหนดหมายเลขดัชนีของรายการได้:

# Replace the raspberry with melon
$array[1] = 'melon'

# Add a fruit to the array
$array += 'banana'

แฮชเทเบิล

ดังที่เราได้เห็นแล้วว่าอาร์เรย์เป็นเพียงรายการ (คอลเลกชัน) ของรายการ ซึ่งเราสามารถเพิ่ม แก้ไข หรือลบออกจากรายการได้ ดัชนีจะถูกสร้างขึ้นโดยอัตโนมัติเมื่อคุณเพิ่มรายการลงไป ในทางตรงกันข้าม ด้วย PowerShell HashTable เราจะต้องกำหนดดัชนี (คีย์) ของค่าที่เราต้องการเพิ่ม

ในการสร้างแฮชเทเบิล เราใช้ {} แทน ():

# Creating a hashtable
$serverIps= @{}

# Or creating a pre-populate hashtable
$serverIps= @{
  'la-srv-lab02' = '192.168.10.2'
  'la-srv-db01' = '192.168.10.100'
}

ในการเพิ่มที่อยู่ IP ของเซิร์ฟเวอร์ลงในแฮชเทเบิล เราจะต้องกำหนดคีย์ เราไม่สามารถทำเพียงแค่ $hashtable.add('value') ได้ เนื่องจาก hashtable จะไม่สร้างดัชนีโดยอัตโนมัติ

$key = 'la-srv-lab01'
$value = '192.168.10.1'
$serverIps.add($key,$value)

# Or simply
$serverIps.add('la-srv-lab03','192.168.10.3')

# Result:
$serverips

Name                           Value
----                           -----
la-srv-lab03                   192.168.10.3
la-srv-lab01                   192.168.10.1

คีย์ในกรณีนี้คือชื่อเซิร์ฟเวอร์และค่าที่อยู่ IP ของเซิร์ฟเวอร์ หากเราต้องการที่อยู่ IP ของเซิร์ฟเวอร์ lab03 เราก็สามารถดำเนินการดังต่อไปนี้:

การดึงข้อมูลจาก Hashtable

ในการดึงข้อมูลจากแฮชเทเบิลใน PowerShell เราสามารถระบุคีย์ ซึ่งจะส่งคืนค่าของคีย์:

$serverIps['la-srv-lab03']

# Result
192.168.10.3

อีกทางเลือกหนึ่งคือการวนซ้ำผ่านแฮชเทเบิล แต่วิธีนี้ทำงานแตกต่างออกไปเล็กน้อยเมื่อเปรียบเทียบกับอาเรย์ หากเราเพียงแค่ไพพ์ foreach ไว้ด้านหลัง hashtable คุณจะสังเกตได้ว่ามันจะส่งคืนเฉพาะวัตถุ hashtable เท่านั้น:

$serverIps | foreach {write-host $_}
System.Collections.Hashtable

หากต้องการรับเฉพาะค่าจาก hashtable เราสามารถใช้คุณสมบัติ .value:

# Return only the values
$serverIps.values

# Or pipe them in a foreach to ping the servers for example:
$serverIps.values | foreach {ping $_}

เมื่อทำงานกับแฮชเทเบิล คุณอาจต้องการดึงข้อมูลเป็นคู่คีย์/ค่าด้วย สำหรับสิ่งนี้ เราสามารถใช้ฟังก์ชัน GetEnumerator:

$serverIps.GetEnumerator() | ForEach-Object {
   $result = '{0} IP address is {1}' -f $_.key, $_.value
   write-host $result
}

# Result
la-srv-lab03 IP address is 192.168.10.3
la-srv-lab01 IP address is 192.168.10.1

กำลังอัปเดตค่า

การอัปเดตค่าใน hashtable สามารถทำได้โดยใช้คีย์เพื่อเลือกคู่คีย์/ค่าที่ถูกต้อง:

$serverIps['la-srv-lab03'] = '192.168.10.5'

หากคุณต้องการอัปเดตหลายค่าใน hashtable คุณไม่สามารถใช้ ForEach loop เพื่อวนซ้ำผ่าน hashtable ได้ ตัวอย่างเช่น สิ่งนี้จะไม่ทำงาน:

$serverIps.Keys | ForEach-Object {
    $serverIps[$_] = '192.168.10.20'
}

ก่อนอื่นคุณจะต้องโคลนคีย์ก่อนจึงจะสามารถอัปเดตค่าได้:

$serverIps.Keys.Clone() | ForEach-Object {
   $serverIps[$_] = '192.168.10.20'
}

การลบคีย์หรือค่า

หากต้องการลบคู่คีย์/ค่าออกจาก hashtable โดยสมบูรณ์ คุณสามารถใช้ฟังก์ชัน .remove คุณจะต้องระบุรหัสที่คุณต้องการลบ:

$serverIps.Remove('la-srv-lab03')

นอกจากนี้ยังสามารถลบเฉพาะค่าออกจากคีย์ได้:

$serverIps['la-srv-lab03'] = $null

หากต้องการล้าง hashtable โดยสมบูรณ์ คุณมีสองตัวเลือก คุณสามารถสร้างอินสแตนซ์ hashtable ใหม่หรือใช้ฟังก์ชัน clear อย่างหลังเป็นที่ต้องการเพราะจะทำให้โค้ดของคุณอ่านง่ายขึ้น

# Recreate the hashtable instance
$serverIps = @{}

# Better option for readability, use the clear function
$serverIps.clear()

สาดแฮชเทเบิล

cmdlet บางตัวใน PowerShell ต้องการคุณสมบัติมากมายที่โดยทั่วไปแล้วเราทุกคนเขียนไว้ในบรรทัดเดียว ซึ่งอาจทำให้สคริปต์ PowerShell ของคุณอ่านยากขึ้น เนื่องจากคุณอาจต้องเลื่อนในแนวนอนเพื่อดูคำสั่งทั้งหมด

ตัวอย่างเช่น เมื่อคุณต้องการส่งอีเมลจาก PowerShell คุณจะต้องมีพารามิเตอร์เป็นบรรทัดยาว

Send-MailMessage -SmtpServer smtp.contoso.com -To johndoe@lazyadmin.nl -From info@contoso.com -Subject 'super long subject goes here' -Body 'Test email from PowerShell' -Priority High

เพื่อให้อ่านง่ายขึ้น เราสามารถใช้แฮชเทเบิลและทำเครื่องหมายไว้ Splatting จะแทนที่พารามิเตอร์และค่าทั้งหมดด้วยตัวแปรตัวเดียว โปรดทราบว่าเราใช้สัญลักษณ์ @ เพื่อระบุตัวแปรแทน $

$mail = @{
  SmtpServer  = 'smtp.contoso.com'
  To          = 'johndoe@lazyadmin.nl'
  From        = 'info@contoso.com'
  Subject     = 'super long subject goes here'
  Body        = 'Test email from PowerShell'
  Priority    = High
}

# Note the @ infront of mail, instead of $
Send-MailMessage @mail

อย่างที่คุณเห็น การสาดจะทำให้โค้ดของคุณอ่านและบำรุงรักษาได้ง่ายขึ้น แทนที่จะต้องใช้พารามิเตอร์เป็นแถวยาวๆ

การสร้างวัตถุจาก Hashtables

Hashtables มีประโยชน์มากเมื่อคุณต้องการจัดโครงสร้างข้อมูลสำหรับออบเจ็กต์เดียวหรือสำหรับการแบ่งแยก แต่สิ่งเหล่านี้ไม่ใช่ออบเจ็กต์ที่แท้จริง Hashtables มีเพียงสองคอลัมน์ คีย์ และค่าเท่านั้น ดังนั้นเราจึงสามารถสร้างแฮชเทเบิลที่มีข้อกำหนดเฉพาะของเซิร์ฟเวอร์เดียว แต่เมื่อเราต้องการจัดเก็บข้อมูลเกี่ยวกับเซิร์ฟเวอร์หลายเครื่อง เราก็พบกับข้อจำกัด (เช่น เราไม่สามารถนำชื่อคอลัมน์กลับมาใช้ซ้ำได้)

ดังนั้นวิธีที่ดีกว่าในการจัดโครงสร้างข้อมูลของคุณเมื่อคุณมีหลายรายการคือการใช้ออบเจ็กต์ วิธีที่ง่ายที่สุดในการสร้างออบเจ็กต์ใน PowerShell คือการแปลงแฮชเทเบิลเป็นออบเจ็กต์ PowerShell แบบกำหนดเอง เราทำสิ่งนี้โดยเพิ่ม [pscustomobject] ไว้หน้าแฮชเทเบิล

ยกตัวอย่างต่อไปนี้ อันดับแรกเราสร้างแฮชเทเบิลที่มีข้อกำหนดเฉพาะของเซิร์ฟเวอร์:

$servers = @{
  'name'    = 'la-srv-db01'
  'ip'      = '192.168.10.100'
  'model'   = 'Hp DL380 G10'
  'memory'  = '96Gb'
}

# Result
Name                           Value
----                           -----
memory                         96Gb
ip                             192.168.10.100
name                           la-srv-db01
model                          Hp DL380 G10

อย่างที่คุณเห็น เรามีเพียงสองคอลัมน์ ชื่อ และค่าเท่านั้น แฮชเทเบิลแสดงถึงเซิร์ฟเวอร์เดียวและเราไม่สามารถใช้มันเพื่อสร้างรายการเซิร์ฟเวอร์ได้

อย่างไรก็ตาม หากเราแปลงแฮชเทเบิลเป็นออบเจ็กต์ PowerShell แบบกำหนดเอง เราจะได้ตารางจริงซึ่งเรามีหลายคอลัมน์

$servers = [pscustomobject]@{
  'name'    = 'la-srv-db01'
  'ip'      = '192.168.10.100'
  'model'   = 'Hp DL380 G10'
  'memory'  = '96Gb'
}

# Result
name        ip             model        memory
----        --             -----        ------
la-srv-db01 192.168.10.100 Hp DL380 G10 96Gb  

ตอนนี้เราสามารถเพิ่มเซิร์ฟเวอร์อื่นให้กับ pscustomobject ได้เช่นกัน:

function servers {
  [pscustomobject]@{
    'name'    = 'la-srv-db01'
    'ip'      = '192.168.10.100'
    'model'   = 'Hp DL380 G10'
    'memory'  = '96Gb'  
  }
  [pscustomobject]@{
    'name'    = 'la-srv-lab03'
    'ip'      = '192.168.10.3'
    'model'   = 'Hp DL180 G9'
    'memory'  = '32Gb'
  }
}

servers

# Result
name         ip             model        memory
----         --             -----        ------
la-srv-db01  192.168.10.100 Hp DL380 G10 96Gb
la-srv-lab03 192.168.10.3   Hp DL180 G9  32Gb

การส่งออก Hashtable เป็น CSV

เมื่อคุณส่งออกแฮชเทเบิลเป็น CSV คุณจะสังเกตเห็นว่าตามค่าเริ่มต้นคีย์และค่าไม่ได้ถูกส่งออก ผลลัพธ์จะมีข้อมูลเกี่ยวกับออบเจ็กต์แฮชเท่านั้น ไม่ใช่ข้อมูลภายในแฮชเทเบิล

หากต้องการส่งออกเนื้อหาของแฮชเทเบิล คุณจะต้องใช้วิธี GetEnumerator เช่นเดียวกับที่เราทำกับการดูเนื้อหาของแฮชเทเบิ้ล เราต้องการเพียงคีย์และค่าจากแฮชเทเบิล ดังนั้นคุณจะต้องเพิ่มการเลือกให้กับคำสั่งด้วย

$serverIps= @{
  'la-srv-lab02' = '192.168.10.2'
  'la-srv-db01' = '192.168.10.100'
  'la-srv-lab03' = '192.168.10.3'
}

$serverIps.GetEnumerator() | Select Key, Value | Export-CSV -path c:\temp\hash.csv -No

ห่อขึ้น

Hashtables ใน PowerShell เป็นวิธีที่ยอดเยี่ยมในการจัดโครงสร้างข้อมูลหรือใช้ร่วมกับการแบ่งส่วน อย่างไรก็ตาม โปรดทราบว่ามีไว้เพื่อใช้สำหรับสินค้าชิ้นเดียวเท่านั้น เราไม่สามารถสร้างคอลัมน์ที่กำหนดเองหรือจัดเก็บหลายแถวด้วยคีย์เดียวกันได้ เพื่อสิ่งนั้น คุณจำเป็นต้องใช้ PowerShell Objects แบบกำหนดเองจริงๆ

ฉันหวังว่าบทความนี้จะมีประโยชน์ หากคุณมีคำถามใด ๆ เพียงแสดงความคิดเห็นด้านล่าง

หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ PowerShell ตรวจสอบให้แน่ใจว่าคุณได้อ่านคำสั่ง PowerShell 10 อันดับแรกที่คุณต้องรู้ด้วย

บทความที่เกี่ยวข้อง