【问题标题】:How to search a collection with an array in Powershell如何在 Powershell 中使用数组搜索集合
【发布时间】:2016-07-29 12:24:49
【问题描述】:

我有一组来自 Outlook 的 MailItems。我想搜索每个邮件项目并根据数组中包含的搜索词列表返回SubjectCategory - 在名为$searchArray 的示例中。

例如:

$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>
}

我想返回Subject,然后是一个名为Category 的列,它将查看$msg.SenderEmailAddress,如果$searchArray 中的任何searchTerms 包含在地址中,则返回具有里面的那个搜索词。

例如,如果 SenderEmailAddress 值之一是“searchTerm2@somewhere.com”,则将 Category1 作为 Category 返回。

【问题讨论】:

  • Nitpick:使用 example.com 作为域示例。
  • 在您的输出中:为了确保所有项目返回正确的数据,它们必须返回相同数量的属性。因此,您要么需要返回所有类别并突出显示您想要的类别,要么有一个自定义字段来显示匹配的类别。一封电子邮件可以匹配多个类别吗?当它发生时会发生什么?您是否偏爱现在的$searchArray 结构?对其进行一些更改将使过程更容易
  • @Matt 我不关心搜索数组的结构。只是我将为每个类别提供一个或多个搜索词。考虑搜索词对所有类别都是唯一的。输出将为每个电子邮件地址分配一个类别。

标签: arrays powershell powershell-3.0


【解决方案1】:

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

$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)]
    }
}

【讨论】:

    【解决方案2】:

    仍然需要像 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 "|"
        }
    }
    

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

    【讨论】:

      【解决方案3】:

      使用开关:

      $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
      }
      

      【讨论】:

        猜你喜欢
        • 2020-10-29
        • 2021-03-30
        • 1970-01-01
        • 1970-01-01
        • 2020-12-12
        • 2017-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多