Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find array elements which values are not part of another array PowerShell

I have two arrays

  • $adg - (A list of AD groups)

  • $dbs - (A list of database names)

Lets say I use this command $adg -match $dbs.i

The output will be all the AD groups which have the string $dbs in its name.

However, I am aiming to find the DBs in which are not part of the AD groups array.

Eg:

$adg = @("Dev22_Owner","Test49_Owner","Rocket_Owner")
$dbs = @("Dev22", "Confidential", "InternDB", "Rocket", "Test49")

What approach should I take to get the output:

Confidential

InternDB

I tried $dbs | Where $adg -notmatch $dbs.i but there is no output.

like image 983
Akmal Avatar asked Feb 19 '18 09:02

Akmal


People also ask

What is array in PowerShell?

PowerShell Arrays. An array is a type of a variable. It is a set of components (array elements) arranged in a certain order. Elements of the array are numbered sequentially, and you access an element using its index number.

How do you access an element in a PowerShell array?

Elements of the array are numbered sequentially, and you access an element using its index number. When creating arrays, be aware of the default PowerShell behavior. If you create an array with multiple elements, PowerShell will create an array, as you intend.

How do I see if an array contains a particular value?

If you want to see if any of the elements in an array contains a particular value, use the Contains method: Even though most of the array operations in PowerShell are relatively easy to accomplish, there is no simply way to delete an array.

How to check if elements are not present in another array?

Use the .filter () method on the first array and check if the elements of first array are not present in the second array, Include those elements in the output. Example 1: This example using the approach discussed above. are not present in another array using JavaScript?


2 Answers

I would first remove the unecessary user part from the ad group:

$groups = $adg | ForEach-Object {
    $_ -replace '_.*?$'
}

Then you can use the Where-Object cmdlet with the -notin operator to filter them:

$dbs | Where-Object { $_ -notin $groups }

Output:

Confidential
InternDB
like image 144
Martin Brandl Avatar answered Oct 19 '22 15:10

Martin Brandl


To offer a more concise PSv3+ alternative to Martin Brandl's helpful answer:

PS> (Compare-Object ($adg -replace '_Owner$') $dbs).InputObject
Confidential
InternDB
  • ($adg -replace '_Owner$') returns a new array with copies of the input string that have _Owner suffix stripped from them.

  • Compare-Object compares the stripped array with the other array and returns objects that represent the differences between the two arrays.

  • Accessing the .InputObject on the difference objects returns the values that differ.

    • Note: If $dbs contained items that aren't in the stripped $adg array, the above would return a union of all differing items, irrespective of which side they're unique to; to distinguish the sides / limit to a side, you'd have to use the .SideIndicator property (value => indicates values exclusive to the right side, <= those exclusive to the left side).

As for what you tried:

$adg -match $dbs.i doesn't work as intended and is effectively the same as $adg -match '', which invariably returns all $adg items.

The reason is that array $dbs has no .i property, so the expression evaluates to $null, which on the RHS of match is coerced to a string and therefore is converted to the empty string.

Generally, the RHS of -match does not support arrays - only a single regular expression.

If you do supply an array, it is implicitly converted to a string by joining the elements to form a space-separated list; e.g. array 1, 2 is coerced to '1 2' and '1 2' -match (1, 2) therefore evaluates to $True.

like image 1
mklement0 Avatar answered Oct 19 '22 15:10

mklement0