web-dev-qa-db-ja.com

PowerShellでの配列変数の比較

2つのフォルダを比較するためのこのスクリプトがあります。

$firstfolder = Get-ChildItem C:\firstfolder
$secondfolder = Get-ChildItem C:\firstfolder

if ($firstfolder -eq $secondfolder) {
Write-Host "Folders are the same."
} else {
    Write-Host "Error: Doesn't match."
}

ご覧のとおり、同じフォルダを比較しています。問題は、配列が等しいことを決して考慮しないということです。どうして?

17
culter

PowerShellでは、配列を指す変数は、配列自体の内容を列挙することによって式で評価されます。

たとえば、次の式:

$firstFolder | Get-Member

System.IO.DirectoryInfo タイプに関する情報を返します。これは、実際には$firstFolder配列のfirst要素のタイプです。配列オブジェクト自体を操作する場合は、,演算子を使用して、オブジェクトを配列として扱うようにPowerShellに明示的に指示する必要があります。次の式:

,$firstFolder | Get-Member

System.Object[]に関する情報を返すことが期待されます。

ただし、2つの配列変数間で-eq演算子を使用すると、状況が少し異なります。実際、PowerShellは左側の配列のみを列挙し、各項目を右側全体の配列と比較します。一致するものがない場合、結果は一致するアイテムの配列またはまったくないになります。例えば:

$a = 1..5
$b = 1..5
$a -eq $b         # returns zero-length array
[bool]($a -eq $b) # returns $false
$a -eq 3          # returns 3

特定のケースでは、$false配列に System.IO.DirectoryInfo オブジェクトが含まれているため、結果は長さゼロの配列(または、 boolean にキャストされた場合は$firstFolder)になります。 $secondFolder変数の配列と一致します。

本当に必要なのは、両方の配列のcontentsを相互に比較することです。ここで、 Compare-Objectコマンドレット が役立ちます。

Compare-Object $firstFolder $secondFolder -SyncWindow 0

これにより、2つの配列間で差異の配列が返されるか、配列が等しい場合は$nullが返されます。より正確には、結果の配列には、一方の配列にのみ存在し、もう一方の配列には存在しない各アイテムのオブジェクトが含まれます。 -SyncWindow 0引数は、配列に表示される項目の順序を違いとしてカウントします。

whatの詳細に触れずに、2つの配列が異なるかどうかを簡単に判断する方法が必要な場合は、_によって返される配列の長さを確認するだけです。 Compare-Object

$areEqual = @(Compare-Object $firstFolder $secondFolder -SyncWindow 0).Length -eq 0

配列に違いがない場合、 Compare-Object$nullを返す可能性があるため、PowerShellに常に結果を配列にパッケージ化するように明示的に指示したことに注意してください。

35

この種の比較では、コマンドレットcompare-objectを使用して、違いがあるかどうかを評価する必要があります。

5
CB.

多分このようなもの。

function arrayequal($a, $b) {
  -not (compare $a $b)
}

arrayequal $a $b

True
1
js2010