2017-05-30 109 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