如何在 Powershell 中使用数组搜索集合

How to search a collection with an array in Powershell

我有一组来自 Outlook 的 MailItems。我想根据数组中包含的搜索词列表搜索每个邮件项目和 return SubjectCategory - 在名为 $searchArray.[= 的示例中21=]

例如:

$mailbox = "my.mailbox@example.com"

$outlook = New-Object -com Outlook.Application
$ns = $outlook.GetNamespace("MAPI")
$inbox = $ns.Folders.Item($mailbox).Folders.Item("Inbox")
$searchItems = $inbox.Folders.Item("MySubFolder").Folders.Item("MyNestedSubFolder").Items

$searchArray = (
    "Category1", ("searchTerm1","searchTerm2","searchTerm3"),
    "Category2", ("searchTerm4","searchTerm5"),
    "Category3", ("searchTerm6")
)

foreach ($msg in $searchItems) {
    $msg | select Subject, # <Category where email address contains one of the search terms>
}

我想 return Subject,然后是名为 Category 的列,该列将查看 $msg.SenderEmailAddress 以及 [= 中是否有任何 searchTerms 14=] 包含在地址中,return 包含该搜索词的类别。

例如,如果 SenderEmailAddress 值之一是 "searchTerm2@somewhere.com",则 return 类别 1 作为 Category

我会翻转这个数组并从中创建一个哈希表。然后使用第一个匹配的搜索词作为类别的查找键:

$searchArray = (
    "Category1", ("searchTerm1","searchTerm2","searchTerm3"),
    "Category2", ("searchTerm4","searchTerm5"),
    "Category3", ("searchTerm6")
)

# Create hashtable
$searchTable = @{}

# Populate hash table with values from array
for($i=0;$i-lt$searchArray.Count;$i+=2){ 
    foreach($term in $searchArray[$i+1])
    {
        $searchTable[$term] = $searchArray[$i]
    }
}

# Select Category based on first matching search term
$msg |Select-Object Subject,@{Name="Category";Expression={
        $sender = $_.SenderEmailAddress
        $searchTable[$($searchTable.Keys |Where-Object{$sender -like "*$_*"} |Select -First 1)]
    }
}

还是需要像Mathias那样使用计算表达式(真的很简单)。但是,我想展示一种方法,其中您拥有 $searchArray 的自定义对象数组。如果你要从头开始定制它,它会看起来像这样。我还将这些术语转换为正则表达式模式匹配,因为您说它们是独一无二的。唯一需要注意的是,您需要确保搜索词中没有正则表达式元字符。

$searchArray = (
    [pscustomobject]@{
        Category = "1"
        Pattern = "searchTerm1|searchTerm2|searchTerm3"
    },  
    [pscustomobject]@{
        Category = "2"
        Pattern = "searchTerm4|searchTerm5"
    },
    [pscustomobject]@{
        Category = "3"
        Pattern = "searchTerm6"}
)

foreach ($msg in $searchItems) {
    $msg | select Subject, @{
        Name="Category";
        Expression={$searchArray | Where-Object{$msg.SenderEmailAddress -match $_.pattern } | Select-Object -ExpandProperty Category}
    } 
}

解决方案依赖于类型加速器 [pscustomobject] 中的 PowerShell 3.0。如果需要,可以轻松地将其恢复到 2.0。


使用 2.0 展示类似的结构,并自动将您的数组转换为适用于我的代码的数组。

$newSearchArray = for($categoryIndex=0;$categoryIndex-lt$searchArray.Count;$categoryIndex+=2){ 
    New-Object -TypeName pscustomobject -Property @{
        Category = $searchArray[$categoryIndex]
        Pattern = ($searchArray[$categoryIndex+1] | ForEach-Object{[regex]::Escape($_)}) -join "|"
    }
}

现在搜索词会自动转义并加入搜索模式。

使用开关:

$mailbox = "my.mailbox@example.com"

$outlook = New-Object -com Outlook.Application
$ns = $outlook.GetNamespace("MAPI")
$inbox = $ns.Folders.Item($mailbox).Folders.Item("Inbox")
$searchItems = $inbox.Folders.Item("MySubFolder").Folders.Item("MyNestedSubFolder").Items

foreach ($msg in $searchItems) {
    $object = $msg | select Subject,Category # <Category where email address contains one of the search terms>
    Switch -Regex ($msg.SenderEmailAddress)
    {
      'searchTerm1|searchTerm2|searchTerm3' { $object.Catetory = 'Category1' ; break }
      'searchTerm4|searchTerm5'             { $object.Catetory = 'Category2' ; break }
      'searchTerm6'                         { $object.Catetory = 'Category3' ; break }
    }
    $object
}