Comparaisons de tableaux facilitées avec PowerShell

À l’aide de quelques tours de passe-passe PowerShell, vous pouvez facilement comparer des tableaux PowerShell de tous types d’objets. Il existe de nombreux scénarios différents dans lesquels vous pourriez vous retrouver, alors creusons et voyons les façons dont nous pouvons construire PowerShell pour comparer des tableaux.

Pour déterminer la meilleure façon de comparer des tableaux, vous devez d’abord comprendre quels types d’éléments se trouvent dans les deux tableaux.

  • Les deux tableaux contiennent-ils tous le même type d’objet ?
  • Les deux tableaux ont-ils le même nombre d’éléments ?
  • Y a-t-il différents types d’objets dans chaque tableau ?

Vous devez connaître la réponse à chacune de ces questions avant de pouvoir comparer précisément des tableaux. Couvrons chaque scénario.

Comparaison de Tableaux de Chaînes de Caractères

Une des façons les plus simples de comparer des tableaux avec PowerShell est si vous avez deux tableaux contenant uniquement des chaînes de caractères. Lorsque vous vous trouvez dans cette situation, vous avez plusieurs façons différentes de comparer les chaînes de caractères dans les tableaux.

Utilisation des Opérateurs -Contains ou -In

L’opérateur -contains est un opérateur PowerShell qui vous permet de vérifier si un objet est dans une collection. L’opérateur -contains ne comprend pas nativement les collections, mais vous pouvez écrire du code pour le faire fonctionner selon vos besoins.

Disons qu’une collection (tableau) contient quatre chaînes de caractères comme ci-dessous.

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

L’opérateur -contains fonctionne en vérifiant si une seule chaîne de caractères se trouve dans ce tableau comme ceci:

$array -contains 'pink'

Quand la collection de gauche contient cette chaîne, PowerShell renverra Vrai. Sinon, il renverra Faux.

PowerShell -contains Operator

Nous pouvons comparer des tableaux en utilisant l’opérateur -contains en lisant chaque chaîne dans un tableau et en vérifiant si l’autre tableau contient cette chaîne.

Disons que je veux comparer deux tableaux pour voir quelles chaînes du premier tableau existent dans le deuxième tableau.

$array = @('blue','red','purple','pink')
$array2 = @('brown','red','black','yellow')

$array | ForEach-Object {
    if ($array2 -contains $_) {
        Write-Host "`$array2 contains the `$array1 string [$_]"
    }
}

Vous pourriez également utiliser l’opérateur -in, qui est identique à l’opérateur -contains, mais la syntaxe est opposée. Lorsque vous utilisez l’opérateur -contains, le tableau est défini du côté gauche. En utilisant l’opérateur -in, le tableau est défini du côté droit comme ci-dessous :

$array | ForEach-Object {
    if ($_ -in $array2) {
        Write-Host "`$array2 contains the `$array1 string [$_]"
    }
}

En utilisant Where-Object

Alternativement, vous pourriez également utiliser la cmdlet Where-Object pour retourner toutes les chaînes dans un tableau dans l’autre comme ci-dessous.

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

En utilisant la cmdlet Compare-Object

Vous pouvez également utiliser PowerShell pour comparer des tableaux en utilisant la cmdlet Compare-Object. Cette cmdlet prend un objet de référence et un objet de différence et renvoie un indicateur de côté indiquant quels éléments sont ou ne sont pas dans l’un ou l’autre tableau.

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

Vous pouvez voir ci-dessous que la cmdlet Compare-Object vous permet de comparer les deux tableaux à la fois. Si la propriété SideIndicator est =>, cela signifie que la propriété InputObject retournée est dans la valeur DifferenceObject et non dans la valeur ReferenceObject et vice versa pour le <= SideIndicator.

Par défaut, Compare-Object renvoie les différences. Vous pouvez également renvoyer toutes les chaînes dans chaque tableau qui se trouvent dans les deux en utilisant le paramètre IncludeEqual.

Comparing arrays with Compare-Object

Comparaison de tableaux d’objets complexes

Assez simple, non ? Maintenant, ajoutons des objets à l’équation. Disons que nous avons un champ dans cette base de données RH et que nous aimerions le peupler dans le champ de description de l’Active Directory. Avant de faire cela, nous devons d’abord avoir un identifiant commun. Dans mon environnement, il y a un numéro d’employé à la fois dans la base de données RH et dans l’attribut personnalisé de l’Active Directory. Alors essayons de faire correspondre cela.

Tout d’abord, voyons ce qui se passe si nous essayons notre approche précédente. Voici le fichier CSV que nous utilisons.

CSV output

Voici comment j’obtiens nos deux ensembles de données.

$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

Que se passe-t-il lorsque nous faisons passer ces deux tableaux par le même scénario que nos chaînes ? Absolument rien. Pourquoi ?

La raison est que vous ne pouvez généralement pas dire $object1 -eq $object2 car les objets sont plus complexes qu’une simple chaîne, un booléen ou un entier. Il y a d’autres circonstances où ce n’est pas le cas, mais j’essaie de prendre l’habitude de comparer les propriétés des objets, pas les objets entiers. Donc dans ce cas, nous devons faire quelque chose comme ça :

$ad_user[0].employeeNumber -eq $users_from_database[0].employeeNumber

Quelle est la solution ? Actuellement, j’ai deux solutions. Lorsqu’il s’agit de milliers d’objets, ce n’est pas rapide mais ça fonctionne. J’aimerais savoir si quelqu’un d’autre a d’autres suggestions.

$ad_employee_numbers = $ad_users | % {$_.employeenumber}

## Créez un tableau de chaînes contenant uniquement le numéro d'employé de l'utilisateur AD
$users_from_database | Where-Object -FilterScript { $ad_employee_numbers -contains $_.employeeNumber }

Nous pouvons également utiliser Compare-Object bien que cela soit plus lent.

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

## Créer un tableau de chaînes contenant uniquement le numéro d'employé de l'utilisateur AD
$database_user_employee_numbers = $users_from_database | ForEach-Object {$_.employeenumber}

## Créer un tableau de chaînes contenant uniquement le numéro d'employé de l'utilisateur de la base de données
(Compare-Object $ad_employee_numbers $database_user_employee_numbers -IncludeEqual | Where-Object -FilterScript {$_.SideIndicator -eq '=='}).InputObject

Conclusion

Il existe de nombreuses façons différentes d’utiliser PowerShell pour comparer des tableaux. Les tableaux peuvent être complexes et une compréhension approfondie des objets à l’intérieur des tableaux vous aidera grandement à les comparer.

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