Confronti di Array Resi Facili con PowerShell

Usando un po’ di kung-fu di PowerShell, puoi facilmente confrontare gli array di tutti i tipi di oggetti PowerShell. Ci sono molti scenari diversi in cui potresti trovarti, quindi approfondiamo e vediamo i modi in cui possiamo costruire PowerShell per confrontare gli array.

Per determinare il modo migliore per confrontare gli array, devi prima capire quali tipi di elementi sono presenti in entrambi gli array.

  • Entrambi gli array contengono lo stesso tipo di oggetto?
  • Entrambi gli array hanno lo stesso numero di elementi?
  • Ci sono tipi di oggetti diversi in ciascun array?

Devi conoscere la risposta a ciascuna di queste domande prima di poter confrontare accuratamente gli array. Copriamo ogni scenario.

Confrontare gli array di stringhe

Uno dei modi più semplici per confrontare gli array con PowerShell è se hai due array contenenti solo stringhe. Quando ti trovi in questa posizione, hai alcuni modi diversi per confrontare le stringhe negli array.

Usando gli operatori -Contains o -In

L’operatore -contains è un operatore di PowerShell che ti consente di verificare se un oggetto è in una raccolta. L’operatore -contains non comprende nativamente le raccolte, ma puoi scrivere del codice per farlo fare ciò che desideri.

Supponiamo che una raccolta (array) contenga quattro stringhe come segue.

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

L’operatore -contains funziona controllando se una singola stringa è presente in quell’array come segue:

$array -contains 'pink'

Quando la raccolta a sinistra contiene quella stringa, PowerShell restituirà True. Se no, restituirà False.

PowerShell -contains Operator

Possiamo confrontare gli array utilizzando l’operatore -contains leggendo ogni stringa in un array e verificando se l’altro array contiene quella stringa.

Supponiamo che voglio confrontare due array per vedere quali stringhe nel primo array esistono nel secondo array.

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

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

In alternativa, è possibile utilizzare l’operatore -in che è identico all’operatore -contains ma la sintassi è opposta. Quando si utilizza l’operatore -contains, l’array viene definito sul lato sinistro. Utilizzando l’operatore -in, l’array viene definito sul lato destro come mostrato di seguito:

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

Utilizzando il cmdlet Where-Object

In alternativa, è possibile utilizzare il cmdlet Where-Object per restituire tutte le stringhe in un array nell’altro come mostrato di seguito.

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

Utilizzando il cmdlet Compare-Object

È anche possibile utilizzare PowerShell per confrontare gli array utilizzando il cmdlet Compare-Object. Questo cmdlet prende un oggetto di riferimento e un oggetto di differenza e restituisce un indicatore laterale che indica quali elementi sono e quali non sono presenti in entrambi gli array.

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

Puoi vedere qui di seguito che il cmdlet Compare-Object ti permette di confrontare entrambi gli array contemporaneamente. Se la proprietà SideIndicator è =>, ciò significa che la proprietà InputObject restituita è nel valore DifferenceObject e non nel valore ReferenceObject e viceversa per l’indicatore laterale <=.

Per impostazione predefinita, Compare-Object restituisce le differenze. È anche possibile restituire tutte le stringhe presenti in ciascun array che sono presenti in entrambi utilizzando il parametro IncludeEqual.

Comparing arrays with Compare-Object

Confronto tra array di oggetti complessi

Abbastanza semplice, giusto? Ora, introduciamo gli oggetti. Supponiamo di avere un campo in questo nostro database HR e vorremmo popolare questo campo nel campo di descrizione di Active Directory. Prima di farlo, dobbiamo avere un identificatore comune. Nel mio ambiente, c’è un numero di dipendente sia nel database HR che nell’attributo personalizzato di Active Directory. Quindi proviamo a fare una corrispondenza.

Prima di tutto, vediamo cosa succede se proviamo il nostro approccio precedente. Ecco il file CSV che stiamo utilizzando.

CSV output

Ecco come ottengo i nostri due set di dati.

$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

Cosa succede quando eseguiamo questi due array attraverso lo stesso scenario delle stringhe? Assolutamente niente. Perché?

Il motivo è che di solito non è possibile dire $object1 -eq $object2 perché gli oggetti sono più complessi di una semplice stringa, booleano o intero. Ci sono altre circostanze in cui questo non è il caso, ma cerco di abituarmi a confrontare le proprietà dell’oggetto; non gli interi oggetti. Quindi in questo caso, dobbiamo fare qualcosa del genere:

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

Qual è la soluzione? Attualmente, ho due soluzioni. Quando si tratta di migliaia di oggetti, non è veloce ma funziona. Mi piacerebbe sapere se qualcun altro ha altre suggerimenti.

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

## Crea un array di stringhe solo con il numero di dipendente dell'utente AD
$users_from_database | Where-Object -FilterScript { $ad_employee_numbers -contains $_.employeeNumber }

Possiamo anche utilizzare Compare-Object, anche se questo è più lento.

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

## Creare un array di stringhe contenente solo il numero di dipendente dell'utente AD
$database_user_employee_numbers = $users_from_database | ForEach-Object {$_.employeenumber}

## Creare un array di stringhe contenente solo il numero di dipendente dell'utente del database
(Compare-Object $ad_employee_numbers $database_user_employee_numbers -IncludeEqual | Where-Object -FilterScript {$_.SideIndicator -eq '=='}).InputObject

Conclusione

Esistono molteplici modi per utilizzare PowerShell per confrontare array. Gli array possono essere complessi e comprendere a fondo gli oggetti all’interno degli array aiuterà notevolmente nel confronto.

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