在powershell中比较csv而不是数组

时间:2016-09-14 18:35:55

标签: arrays powershell csv

我正在尝试编辑执行以下操作的脚本: 它比较两个数组并从第一个数组中删除已知的不可用字符串 它会轮询AD并打印在AD中找不到的所有字符串。

问题是,我不想最初使用数组,我想使用csv。好吧,另一个问题是我对Powershell感觉很好。我已对此进行了编辑,因此我没有使用实数,但这是我所拥有的。请帮忙。

# Find free numbers in AD
$numberRanges = @(
  @(6667778001,6667778999), 
  @(6667776001,6667777999)
)
[System.Collections.ArrayList]$knownUnavailable = 6667778203,6667777212,6667777213

[System.Collections.ArrayList]$knownUnavailableU64 = @()
foreach ( $knownUnavailableItem in $knownUnavailable ) {
  $knownUnavailableU64 += [UInt64]$knownUnavailableItem
}

$strFilter = '(&(objectCategory=User)(telephonenumber=*-*-*))'
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree" 
$colResults = $objSearcher.FindAll()
$aDNumbers = @()
foreach ($objResult in $colResults) {
  $objItem = $objResult.Properties
  $aDNumbers+=[UInt64]($objItem.telephonenumber.Replace("-",""))
}
$availableNumbers = @()
foreach ($numberSet in $numberRanges) {
  $lowerBound=[UInt64]$numberSet[0]
  $upperBound=[UInt64]$numberSet[1]
  for($i = $lowerBound; $i -le $upperBound; $i++) { 
    if ( !( $aDNumbers.Contains($i)) -and !( $knownUnavailableU64.Contains($i) )
    ) {
      $availableNumbers+=$i
    }
  }
  [array]::sort($availableNumbers)
}
$availableNumbers | % { "{0:##########}" -f $_ }

write-host "Press any key to close..."
[void][System.Console]::ReadKey($true)

理想情况下,我会使用这种类型的csv并完全跳过这些数组:

knownDID,usable
6667778001,
6667778002,
6667778003,FALSE
6667778004,
6667778005,

感谢阅读!

1 个答案:

答案 0 :(得分:2)

    Array / ArrayList上的
  1. +=每次都会重新创建它。使用ArrayList' Add方法并将其输出(新项目索引)重定向到$ null
  2. 不是在循环中处理数组元素,而是通过管道ForEach{}处理整个数组,并将输出分配给变量,以便它一次接收新数组。
  3. 要转换数组,只需使用类型转换:$b = [uint64[]]@(1,2,3)(在类型后注意[])。
  4. 使用.NET3.5 + HashSet.ExceptWith而不是手动枚举大型数组,速度要快几个数量级。两个对象应首先转换为HashSet(使用类型转换)。
  5. $numberRanges = @(
        [UInt64[]]@(6667778001,6667778999)
        [UInt64[]]@(6667776001,6667777999)
    )
    
    $knownUnavailable = [Collections.Generic.HashSet[UInt64]](
        Import-Csv c:\knownDID.csv |
            Where { $_.usable -eq 'false' } |
            Select -expand knownDID
    )
    
    $objSearcher = [DirectoryServices.DirectorySearcher]::new(
        [DirectoryServices.DirectoryEntry]::new(),
        '(&(objectCategory=User)(telephonenumber=*-*-*))',
        [Collections.Specialized.StringCollection]@('telephonenumber'),
        'Subtree'
    )
    $objSearcher.PageSize = 1000
    
    $aDNumbers = [Collections.Generic.HashSet[UInt64]](
        $objSearcher.FindAll() | ForEach { $_.Properties.telephonenumber -replace '-','' }
    )
    
    $availableNumbers = $numberRanges | ForEach {
        $numberSet = [Collections.Generic.HashSet[UInt64]]@($_[0]..$_[1])
        $numberSet.ExceptWith($aDNumbers)
        $numberSet.ExceptWith($knownUnavailable)
        $numberSet
    }
    
    $availableNumbers | %{ '{0:##########}' -f $_ }
    
    Write-Host "Press any key to close..."
    [void][System.Console]::ReadKey($true)
    

    代码未经测试,因此请将其用作可能的方法示例。