【问题标题】:Powershell - remove duplicates from 2 arrays using wildcardsPowershell - 使用通配符从 2 个数组中删除重复项
【发布时间】:2018-02-25 02:18:26
【问题描述】:

我正在尝试从 2 个查询的输出中删除重复项并仅保留唯一条目。

我正在使用以下内容提取已安装的 Windows 更新列表(同时去除 12 个字符的空格并降为小写:

$A = @(Get-HotFix | select-object @{Expression={$_.HotFixID.ToLower()}} | ft -hidetableheaders | Out-String) -replace '\s{12}',''

然后我查询文件夹中可用文件的列表并使用以下方法去除 3 个尾随空白字符:

$B = @(Get-ChildItem D:\y | select-object 'Name' | ft -hidetableheaders | Out-String) -replace '\s{3}',''

我遇到的问题是第一个查询 ($A) 返回如下输出:

kb4040981
kb4041693
kb2345678
kb8765432

而第二个查询 ($B) 返回如下输出:

windows8.1-kb4040981-x64_d1eb05bc8c55c7632779086079c7759f40d7386f.cab
windows8.1-kb4041687-x64_3bdf264bcfc0dda01c2eaf2135e322d2d6ce6c64.cab
windows8.1-kb4041693-x64_359b7ac71a48e5af003d67e3e4b80120a2f5b570.cab
windows8.1-kb4049179-x64_e6ec21d5d16fa6d8ff890c0c6042c2ba38a1f7c4.cab

我需要在 $A 数组中的每个条目周围使用通配符来比较 2 个输出(我认为),并且它存在于 $B 中的位置从 $B 数组中删除整行。

我无法截断 $B 的输出,因为我需要在后续过程中使用完整的文件名。

在上面的示例输出中,整个 FIRST 和 THIRD 行将从 $B 数组中删除,其他行保持不变。

我尝试了很多在线搜索的方法,并使用了 foreach 循环,但都无济于事。

提前感谢您的帮助。

【问题讨论】:

    标签: arrays powershell duplicates wildcard


    【解决方案1】:

    您对不起作用的 foreach 循环进行了哪些尝试?除非您的输出很大,否则此方法非常简单。

    $a = "kb4040981","kb4041693","kb2345678","kb8765432","test"
    [System.Collections.ArrayList]$b = "windows8.1-kb4040981-x64_d1eb05bc8c55c7632779086079c7759f40d7386f.cab","windows8.1-kb4041687-x64_3bdf264bcfc0dda01c2eaf2135e322d2d6ce6c64.cab","windows8.1-kb4041693-x64_359b7ac71a48e5af003d67e3e4b80120a2f5b570.cab","windows8.1-kb4049179-x64_e6ec21d5d16fa6d8ff890c0c6042c2ba38a1f7c4.cab"
    
    $toRemove = New-Object System.Collections.ArrayList
    
    foreach($kb in $a)
    {
        foreach($line in $b)
        {
            if($line -match $kb)
            {
                write-host "$kb found in: $line" -ForegroundColor Green
                $toRemove.add($line) | out-null
            }
        }
    }
    
    foreach($line in $toRemove)
    {
        $b.Remove($line)
    }
    
    $b
    

    希望对您有所帮助。

    【讨论】:

    • 感谢您的回复。如果声明了数组,那确实有效,但根据我的初始帖子从查询中创建变量时则无效。我尝试将查询输出到文本文件并再次导入它们,但这不起作用。我认为这可能与多行输出有关,但不确定。我仍在坚持,任何其他指针都非常感谢!再次感谢。
    • 您没有理由将它们发送到文件并重新读取它们。您所说的“不起作用”是什么意思,您得到的输出与您期望的输出是什么?跨度>
    • 输出是分配给$B 的完整查询,即不会删除重复项。那是使用您建议的完全相同的代码,但根据 OP 将声明的字符串替换为查询。我也尝试过其他具有相同效果的代码。换句话说,这 2 个查询的输出似乎更难进行比较和删除欺骗。谢谢。
    • 这可能是由于您格式化输出的奇怪方式。使用 format-table、out-string 和您的 -replace 似乎都很奇怪。为什么不只是(Get-ChildItem D:\y -file).name(get-hofix).hotfixID)?你肯定会从学习基础知识中受益。
    • 谢谢您,您完全正确。一旦我简化了查询,您之前的代码就可以完美运行。再次感谢您的耐心和投入。我确实会多学习!
    【解决方案2】:

    我建议您花一点时间来学习 Powershell 的基础知识。当您使用格式 cmdlet 和文本文件而不是对象时,您会忽略好东西。 ;-) 以下是我将如何开始任务:

    $A = Get-HotFix
    $B = Get-ChildItem D:\y | Select-Object -Property Name,@{Name='HotFixID';Expression={($_.BaseName -split '-')[1]}}
    Compare-Object -ReferenceObject $A -DifferenceObject $B -Property 'HotFixID' -PassThru
    

    【讨论】:

    • 如果我指定一个字符串,我会更进一步,但这仍然不能真正比较第一个查询的输出。抱歉,如果我不了解 Powershell,这就是为什么我在搜索和测试其他方法 2 天后在这里询问的原因。 code 获取子项 D:\y | Where-Object {$_ -notmatch 'kb4074588'} |设置内容 c:\z\result.txt code
    • 这就是为什么我建议学习基础知识。您无法通过猜测或一起复制您不理解的代码来学习。你试过我发布的代码吗?发生了什么事?您应该完整阅读您使用的所有 cmdlet(我发布的 cmdlet)的帮助,包括。的例子。您可以从这里开始:Getting Started with Microsoft PowerShell .. 这不会花很长时间,但它会推动您快速前进。
    【解决方案3】:

    衷心感谢 sambardo 的耐心和投入!基于他的出色建议的最终工作解决方案是:

    $a = (Get-Hotfix).hotfixID
    $b = (Get-ChildItem D:\y\ -file *.cab).name
    $toRemove = New-Object System.Collections.ArrayList
      foreach($kb in $a)
    {
        foreach($line in $b)
      {
          if($line -match $kb)
        {
    #            write-host "$kb found in: $line" -ForegroundColor Green
                $toRemove.add($line) | out-null
          }
        }
    }
    foreach($line in $toRemove)
    {
      $b.Remove($line)
    }
    $b
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-21
      • 2018-07-10
      • 2019-06-22
      • 2010-11-26
      • 2012-12-06
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多