2017-05-30 95 views

回答

1

ConnorLSW's helpful answer效果很好,但你可以简化为一个单一的Select-Object呼叫定义计算财产,这也执行得更好:

$file1Objects = Import-Csv .\file1.csv -Delimiter "`t" 
$file2Objects = Import-Csv .\file2.csv -Delimiter "`t" 

$decoratedFile1Objects = $file1Objects | Select-Object *, 
    @{ n='Patched'; e={ ('No', 'Yes')[$file2Objects.CommanName -contains $_.CommanName] } } 

Get-Help -Detailed Select-Object简要介绍了计算性能是如何工作的;有关更详细的解释,请参阅我的this answer

注意使用成语(<choice-A>, <choice-B>)[<Boolean-Test>]的用于基于布尔测试的结果的两个选择之一:

  • ('No', 'Yes')是一个字符串阵列具有元素No(指数0)和Yes(索引1 )。
  • $file2Objects.CommanName -contains $_.CommanName是,在一个数组索引[...])的上下文中使用时被强制转换为布尔表达式要么0(如果$False)或1(如果$True)。
  • 换句话说:

    • 如果布尔表达式返回$False,索引0被使用,导致串No
    • 如果布尔表达式返回$True,则使用索引1,从而产生字符串Yes
  • 注意,这种方法是解决方法对PowerShell的缺乏三元条件语句其他语言,如C#,已经和其中的分支指定的顺序是逆转

    • C#伪代码:<Boolean-Test> ? "Yes" : "No"
    • PowerShell的解决方法:('No', 'Yes')[<Boolean-Test>]
    • 除了分支/选择的排序之外,还有另一个重要的区别:如果您的数组元素是命令/表达式,那么他们是所有评估,无论选择哪一个(无短路)。
    • 有一个出色的feature request for ternary conditionals

至于你试过

你嵌套foreach -loop方法:

  • -patched不创建的输出对象行
  • ,并为修补行创建一个新的对象,其只有属性是新的。

下面的代码解决这些问题,再次依靠Select-Object添加新的属性:

$decoratedFile1Objects = foreach ($f1 in $file1) { 
    # Add property and default to 'No' 
    $f1Decorated = Select-Object -InputObject $f1 *, @{ n='Patched'; e={ 'No' } } 
    foreach($f2 in $file2) { 
    if ($f1.CommanName -eq $f2.CommanName) { 
     # Match found: set property to 'Yes' and exit the inner loop 
     $f1Decorated.Patched = 'Yes' 
     break 
    } 
    } 
    $f1Decorated # Output the decorated object. 
} 

然而,使用PowerShell的-contains-in阵列成员测试运营商的不仅是方便多了,但也表现更好。

+0

@AtulD:很高兴听到它。为了清楚起见,我添加了一个类似于'$ all = ...'的变量赋值。 – mklement0

3

您的CSV文件格式不正确,所以我可以“T可以肯定,如果这是你所需要的东西,但是这个应该指向你在正确的方向:

$File1 = Import-Csv .\file1.csv -Delimiter "`t" 
$File2 = Import-Csv .\file2.csv -Delimiter "`t" 

$NewFile1 = $File1 | % { 
    $Obj = [PSCustomObject]$_ 
    $Obj | Add-Member -Mem NoteProperty -Name Patched -Value ([bool]($_.CommanName -in $File2.CommanName)) 
    return $Obj 
} 

$NewFile1 

将输出

Server HotfixID CommanName  Patched 
------ -------- ----------  ------- 
apdk778 kb3333 apdk778 kb3333  True 
apdk778 yn2919 apdk778 yn2919  True 
apdk778 lk4898 apdk778 lk4898  True 
iijka211 kb3333 iijka211 kb3333 False 
iijka211 yn2919 iijka211 yn2919 True 
iijka211 lk4898 iijka211 lk4898 True 

我更换了前两个集空格与选项卡为了读取CSV文件。

+0

这是否会检查给定的'服务器',或只是'CommanName'跨所有服务器?我认为你必须过滤掉'$ File2'的一个子集,例如'$ serverDetails = $ File2 | Where-Object {$ _。Server -eq $ Obj.Server}'。欣赏这个不清楚的问题 – gms0ulman

+2

@ gms0ulman他已经包含了一个包含服务器名称和更新的列 - 我想 - 如果我错了关于Csv格式,我可以用双循环解决方案更新,我想这个对他来说没问题。 – ConnorLSW

+0

好点,我错过了'CommanName'是另外两列合起来的。 – gms0ulman