배열 비교를 쉽게 만드는 PowerShell로

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 [$_]"
    }
}

대신에 -contains 연산자 대신에 -in 연산자를 사용할 수도 있습니다. -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 }

Compare-Object Cmdlet을 사용하는 방법

Compare-Object cmdlet을 사용하여 PowerShell에서 배열을 비교할 수도 있습니다. 이 cmdlet은 참조 개체와 차이 개체를 가져와 각 배열에 있는 요소가 있는지 여부를 나타내는 측면 표시기를 반환합니다.

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

Compare-Object cmdlet을 사용하면 아래에서 볼 수 있듯이 두 배열을 동시에 비교할 수 있습니다. SideIndicator 속성이 =>인 경우, 이는 반환된 InputObject 속성이 DifferenceObject 값에 있고 ReferenceObject 값에는 없음을 의미하며, <= SideIndicator 경우에는 그 반대입니다.

기본적으로 Compare-Object는 차이점을 반환합니다. IncludeEqual 매개변수를 사용하여 각 배열에 있는 모든 문자열을 반환할 수도 있습니다.

Comparing arrays with Compare-Object

복잡한 객체 배열 비교하기

이해하기 쉽죠? 이제 객체를 추가해 보겠습니다. 우리의 HR 데이터베이스에 필드가 있고 이를 Active Directory 설명 필드에 넣고 싶습니다. 그러기 위해서는 먼저 공통 식별자가 필요합니다. 제 환경에서는 HR 데이터베이스와 사용자 정의 Active Directory 속성에 모두 직원 번호가 있습니다. 이를 일치시켜 보겠습니다.

먼저, 이전 접근 방식을 시도했을 때 어떻게 되는지 확인해 보겠습니다. 사용하는 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}

## AD 사용자의 직원 번호만으로 문자열 배열 생성
$users_from_database | Where-Object -FilterScript { $ad_employee_numbers -contains $_.employeeNumber }

우리는 또한 이것이 느리긴 하지만 Compare-Object를 사용할 수도 있습니다.

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

## AD 사용자의 직원 번호만 가지고 있는 문자열 배열을 생성합니다.
$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/