การเรียนรู้ PowerShell เปรียบเทียบอาร์เรย์อันทรงพลัง
การใช้ PowerShell กังฟูทำให้ Powershell เปรียบเทียบอาร์เรย์ของวัตถุทุกประเภทได้อย่างง่ายดาย มีสถานการณ์ต่างๆ มากมายที่คุณอาจพบว่าตัวเองเผชิญ ดังนั้นเรามาเจาะลึกและดูวิธีที่เราสามารถสร้าง PowerShell เพื่อเปรียบเทียบอาร์เรย์กันดีกว่า
ในการกำหนดวิธีที่ดีที่สุดในการเปรียบเทียบอาร์เรย์ คุณต้องทราบก่อนว่าองค์ประกอบประเภทใดในทั้งสองอาร์เรย์
- อาร์เรย์ทั้งสองมีวัตถุประเภทเดียวกันทั้งหมดหรือไม่
- อาร์เรย์ทั้งสองมีจำนวนองค์ประกอบเท่ากันหรือไม่
- แต่ละอาร์เรย์มีวัตถุประเภทต่างๆ กันหรือไม่
คุณต้องรู้คำตอบของคำถามแต่ละข้อก่อนจึงจะสามารถเปรียบเทียบอาร์เรย์ได้อย่างแม่นยำ มาครอบคลุมแต่ละสถานการณ์กันดีกว่า
การเปรียบเทียบอาร์เรย์ของสตริง
วิธีที่ง่ายที่สุดวิธีหนึ่งในการเปรียบเทียบอาร์เรย์กับ PowerShell คือถ้าคุณมีสองอาร์เรย์ที่มีเพียงสตริงเท่านั้น เมื่อคุณพบว่าตัวเองอยู่ในตำแหน่งนี้ คุณจะมีวิธีต่างๆ สองสามวิธีในการเปรียบเทียบสตริงในอาร์เรย์
การใช้ตัวดำเนินการ -Contains หรือ -In
ตัวดำเนินการ -contains คือตัวดำเนินการ PowerShell ที่ให้คุณตรวจสอบเพื่อดูว่ามีออบเจ็กต์อยู่ในคอลเลกชันหรือไม่ ตัวดำเนินการ -contains ไม่เข้าใจคอลเลกชั่น แต่คุณสามารถสร้างโค้ดเพื่อให้เป็นไปตามการเสนอราคาของคุณได้
สมมติว่าคอลเลกชัน (อาร์เรย์) มีสี่สตริงเหมือนด้านล่าง
$array = @('blue','red','purple','pink')ตัวดำเนินการ -contains ทำงานโดยตรวจสอบว่ามีสตริงเดี่ยวอยู่ในอาร์เรย์นั้นหรือไม่ ดังนี้:
$array -contains 'pink'เมื่อคอลเลกชันทางด้านซ้าย มี สตริงนั้น PowerShell จะส่งกลับค่า True ถ้าไม่เช่นนั้นก็จะคืนค่าเป็นเท็จ
เราสามารถเปรียบเทียบอาร์เรย์โดยใช้ตัวดำเนินการ -contains โดยการอ่านแต่ละสตริงในอาร์เรย์และตรวจสอบว่าอาร์เรย์อื่น มี สตริงนั้นหรือไม่
สมมติว่าฉันต้องการเปรียบเทียบสองอาร์เรย์เพื่อดูว่ามีสตริงใดในอาร์เรย์แรกที่มีอยู่ในอาร์เรย์ที่สอง
$array = @('blue','red','purple','pink')
$array2 = @('brown','red','black','yellow')
$array | ForEach-Object {
if ($array2 -contains $_) {
Write-Host "`$array2 contains the `$array1 string [$_]"
}
}หรือคุณสามารถใช้ตัวดำเนินการ -in ซึ่งเหมือนกับตัวดำเนินการ -contains แต่ไวยากรณ์กลับตรงกันข้าม เมื่อใช้ตัวดำเนินการ -contains อาร์เรย์จะถูกกำหนดทางด้านซ้าย เมื่อใช้ตัวดำเนินการ -in อาร์เรย์จะถูกกำหนดไว้ทางด้านขวาดังภาพด้านล่าง:
$array | ForEach-Object {
if ($_ -in $array2) {
Write-Host "`$array2 contains the `$array1 string [$_]"
}
}การใช้ Where-Object
หรือคุณสามารถใช้ Where-Object cmdlet เพื่อส่งคืนสตริงทั้งหมดในอาร์เรย์หนึ่งในอีกอาร์เรย์เหมือนด้านล่าง
$array | Where-Object -FilterScript { $_ -in $array2 }การใช้การเปรียบเทียบ-Object Cmdlet
คุณยังสามารถใช้ PowerShell เพื่อเปรียบเทียบอาร์เรย์โดยใช้ Compare-Object cmdlet cmdlet นี้รับวัตถุอ้างอิงและวัตถุที่แตกต่างและส่งกลับตัวบ่งชี้ด้านข้างเพื่อระบุว่าองค์ประกอบใดอยู่และไม่ได้อยู่ในอาร์เรย์ใดอาร์เรย์หนึ่ง
Compare-Object -ReferenceObject $array -DifferenceObject $array2
คุณสามารถดูด้านล่างได้ว่า Compare-Object cmdlet ช่วยให้คุณสามารถเปรียบเทียบอาร์เรย์ทั้งสองพร้อมกันได้ หากคุณสมบัติ SideIndicator เป็น => หมายความว่าคุณสมบัติ InputObject ที่ส่งคืนอยู่ในค่า DifferenceObject และไม่ได้อยู่ในค่า ค่า ReferenceObject และในทางกลับกันสำหรับ <= SideIndicator
ตามค่าเริ่มต้น Compare-Object จะส่งกลับค่าความแตกต่าง คุณยังสามารถส่งคืนสตริงทั้งหมดในแต่ละอาร์เรย์ที่อยู่ในทั้งสองอาร์เรย์ได้โดยใช้พารามิเตอร์ IncludeEqual
การเปรียบเทียบอาร์เรย์ของวัตถุที่ซับซ้อน
ง่ายพอใช่มั้ย? ตอนนี้เรามานำวัตถุต่างๆ มาผสมกัน สมมติว่าเรามีฟิลด์ในฐานข้อมูล HR นี้ของเรา และเราต้องการเติมข้อมูลนี้ลงในฟิลด์คำอธิบาย Active Directory ก่อนที่จะดำเนินการนี้ เราต้องมีตัวระบุร่วมกันก่อน ในสภาพแวดล้อมของฉัน มีหมายเลขพนักงานทั้งในฐานข้อมูล HR และในแอตทริบิวต์ Active Directory แบบกำหนดเอง เรามาลองจับคู่สิ่งนี้กัน
ขั้นแรก เรามาดูว่าจะเกิดอะไรขึ้นหากเราลองใช้แนวทางเดิม นี่คือไฟล์ CSV ที่เราใช้
นี่คือวิธีที่ฉันได้รับชุดข้อมูลทั้งสองของเรา
$ad_users = Get-AdUser -Filter {enabled -eq $true} -Properties employeeNumber | select employeenumber,samaccountname,description
$users_from_database = Import-Csv 'database_users.csv' | select employee numberจะเกิดอะไรขึ้นเมื่อเรารันอาร์เรย์ทั้งสองนี้ผ่านสถานการณ์เดียวกันกับสตริงของเรา ไม่มีอะไรจริงๆ. ทำไม
สาเหตุเป็นเพราะว่าปกติคุณไม่สามารถพูดว่า $object1 -eq $object2 ได้ เนื่องจากอ็อบเจ็กต์มีความซับซ้อนมากกว่าสตริงธรรมดา บูลีน หรือจำนวนเต็ม มีบางสถานการณ์ที่ไม่เป็นเช่นนั้น แต่ฉันพยายามทำให้เป็นนิสัยในการเปรียบเทียบคุณสมบัติของวัตถุ ไม่ใช่วัตถุทั้งหมด ดังนั้นในกรณีนี้ เราจะต้องดำเนินการดังนี้:
$ad_user[0].employeeNumber -eq $users_from_database[0].employeeNumberวิธีแก้ปัญหาคืออะไร? ขณะนี้ฉันมีสองวิธีแก้ไข เมื่อจัดการกับวัตถุนับพัน มันไม่รวดเร็วแต่ใช้งานได้ ฉันต้องการทราบว่ามีใครมีข้อเสนอแนะอื่น ๆ หรือไม่
$ad_employee_numbers = $ad_users | % {$_.employeenumber}
## Create an array of strings of only the AD user's employee number
$users_from_database | Where-Object -FilterScript { $ad_employee_numbers -contains $_.employeeNumber }
นอกจากนี้เรายังสามารถใช้ Compare-Object ได้แม้ว่าจะช้ากว่าก็ตาม
$ad_employee_numbers = $ad_users | ForEach-Object {$_.employeenumber}
## Create an array of strings of only the AD user's employee number
$database_user_employee_numbers = $users_from_database | ForEach-Object {$_.employeenumber}
## Create an array of strings of only the database user's employee number
(Compare-Object $ad_employee_numbers $database_user_employee_numbers -IncludeEqual | Where-Object -FilterScript {$_.SideIndicator -eq '=='}).InputObjectบทสรุป
มีหลายวิธีในการใช้ PowerShell เพื่อเปรียบเทียบอาร์เรย์ อาร์เรย์อาจมีความซับซ้อนและการทำความเข้าใจวัตถุภายในอาร์เรย์อย่างละเอียดจะช่วยให้คุณเปรียบเทียบได้อย่างมาก



