مقارنة الأنماط بسهولة باستخدام PowerShell

باستخدام بعض حيل PowerShell، يمكنك بسهولة مقارنة مصفوفات PowerShell لجميع أنواع الكائنات. هناك العديد من السيناريوهات المختلفة التي قد تجدها لذا دعونا نستكشف الطرق التي يمكننا من خلالها بناء PowerShell لمقارنة المصفوفات.

لتحديد أفضل طريقة لمقارنة المصفوفات، يجب عليك أولاً معرفة أنواع العناصر الموجودة في كلتا المصفوفتين.

  • هل تحتوي كلتا المصفوفتين على نفس نوع الكائن؟
  • هل تحتوي كلتا المصفوفتين على نفس عدد العناصر؟
  • هل هناك أنواع مختلفة من الكائنات في كل مصفوفة؟

يجب عليك معرفة إجابة كل هذه الأسئلة قبل أن تتمكن من مقارنة المصفوفات بدقة. دعونا نغطي كل سيناريو.

مقارنة مصفوفات السلاسل

واحدة من أسهل الطرق لمقارنة المصفوفات باستخدام PowerShell هي إذا كانت لديك مصفوفتان تحتويان فقط على سلاسل. عندما تجد نفسك في هذا الموقف، لديك بعض الطرق المختلفة لمقارنة السلاسل في المصفوفات.

استخدام المشغلات -Contains أو -In

المشغل -contains هو مشغل PowerShell يسمح لك بالتحقق مما إذا كان كائن موجودًا في مجموعة. المشغل -contains لا يفهم المجموعات بشكل أساسي ولكن يمكنك بناء كود لجعله يفعل ما تريد.

لنفترض أن مجموعة (مصفوفة) تحتوي على أربع سلاسل مثل ما يلي.

$array = @('blue','red','purple','pink')

يعمل المشغل -contains عن طريق التحقق مما إذا كانت سلسلة واحدة موجودة في تلك المصفوفة مثل هذا:

$array -contains 'pink'

عندما تحتوي المجموعة على السلسلة على اليسار يحتوي على، سيعيد PowerShell قيمة True. إذا لم يكن الأمر كذلك، سيعيد False.

PowerShell -contains Operator

يمكننا مقارنة الصفائف باستخدام المشغل -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

بالإضافة إلى ذلك، يمكنك أيضًا استخدام cmdlet Where-Object لإرجاع جميع السلاسل في صف واحد في الصف الآخر كما يلي.

$array | Where-Object -FilterScript { $_ -in $array2 }

استخدام Compare-Object Cmdlet

يمكنك أيضًا استخدام PowerShell لمقارنة الصفائف باستخدام cmdlet Compare-Object. يأخذ هذا الأمر النصي المرجعي والنص الفارق ويعيد مؤشر الجانب الذي يشير إلى العناصر التي تكون والتي ليست في أي من الصفائف.

Compare-Object -ReferenceObject $array -DifferenceObject $array2
Using Compare-Object

يمكنك أن ترى أدناه أن cmdlet Compare-Object يتيح لك مقارنة كل من الصفائف في وقت واحد. إذا كانت خاصية SideIndicator هي =>، فهذا يعني أن خاصية InputObject التي تم إرجاعها في قيمة DifferenceObject وليست في قيمة ReferenceObject والعكس صحيح بالنسبة للـ <= SideIndicator.

بشكل افتراضي، Compare-Object يعيد الفروقات. يمكنك أيضًا إعادة جميع السلاسل في كل مصفوفة التي تكون في كلتاهما باستخدام المعامل IncludeEqual.

Comparing arrays with Compare-Object

مقارنة مصفوفات الكائنات المعقدة

بسيط بما فيه الكفاية، أليس كذلك؟ الآن، دعونا نضيف الكائنات إلى الخليط. لنقل أن لدينا حقل في قاعدة البيانات الخاصة بنا للموارد البشرية ونود ملء هذا في حقل وصف الدليل النشط. قبل القيام بذلك، يجب علينا أولاً أن يكون لدينا معرف مشترك. في بيئتي، هناك رقم موظف في قاعدة بيانات الموارد البشرية وفي السمة المخصصة لدليل النشط. لذا دعونا نحاول تطابق هذا.

أولاً، دعونا نرى ما يحدث إذا جربنا النهج السابق. إليكم ملف CSV الذي نستخدمه.

CSV output

هكذا أحصل على مجموعتي البيانات.

$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}

## إنشاء مصفوفة من السلاسل فقط لرقم موظف المستخدم في دليل النشط
$users_from_database | Where-Object -FilterScript { $ad_employee_numbers -contains $_.employeeNumber }

نستطيع أيضًا استخدام Compare-Object على الرغم من أن هذا أبطأ.

$ad_employee_numbers = $ad_users | ForEach-Object {$_.employeenumber}

## إنشاء مصفوفة من السلاسل تحتوي فقط على رقم الموظف لمستخدم Active Directory
$database_user_employee_numbers = $users_from_database | ForEach-Object {$_.employeenumber}

## إنشاء مصفوفة من السلاسل تحتوي فقط على رقم الموظف لمستخدم قاعدة البيانات
(Compare-Object $ad_employee_numbers $database_user_employee_numbers -IncludeEqual | Where-Object -FilterScript {$_.SideIndicator -eq '=='}).InputObject

الختام

هناك العديد من الطرق المختلفة لاستخدام PowerShell لمقارنة المصفوفات. يمكن أن تكون المصفوفات معقدة وفهم الكائنات داخل المصفوفات بشكل جيد سيساعد كثيرًا في مقارنتها.

Source:
https://adamtheautomator.com/powershell-compare-arrays/