2016-12-14 40 views
1

我有3個文本文件的文件夾。 文件1,稱之爲test1.txt的具有價值遍歷txt文件並找到並非在所有文件中的行

11 
22 
22 

Test2.txt已經值

11 
22 
22 
33 

test3.txt具有值

11 
22 
22 
33 
44 
44 

我怎樣才能讓我的最終結果等於至(New.txt) 成爲:

44 
44 

此值不在其他2個文件中,所以這是我想要的。

到目前爲止代碼:

$result = "C:\NonDuplicate.txt" 

$filesvalues=gci "C:\*.txt" | %{$filename=$_.Name; gc $_ | %{[pscustomobject]@{FileName= $filename; Row=$_ }}} 

#list file where not exists others file with same value 
$filesvalues | % { 
        $valtockeck=$_ 
        [pscustomobject]@{ 
             Val=$valtockeck 
             Exist=$filesvalues.Where({ $_.FileName -ne $valtockeck.FileName -and $_.Row -eq $valtockeck.Row }).Count -gt 0 
            } 

       } | 

       where Exist -NE $true | 
       % {$_.Val.Row | out-file $result -Append} 

這是錯誤:

Where-Object : Cannot bind parameter 'FilterScript'. Cannot convert the "Exist" value of type "System.String" to type "System.Management.Automation.ScriptBlock". 
At line:16 char:23 
+     where <<<< Exist -NE $true | 
    + CategoryInfo   : InvalidArgument: (:) [Where-Object], ParameterBindingException 
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WhereObjectCommand 

回答

1

試試這個

#list files/values couple 
$filesvalues=gci "C:\temp\test\test*.txt" -file | %{$filename=$_.Name; gc $_ | %{[pscustomobject]@{FileName= $filename; Row=$_ }}} 

#list file where not exists others file with same value 
$filesvalues | % { 
        $valtockeck=$_ 
        [pscustomobject]@{ 
             Val=$valtockeck 
             Exist=$filesvalues.Where({ $_.FileName -ne $valtockeck.FileName -and $_.Row -eq $valtockeck.Row }).Count -gt 0 
            } 

       } | 

       where Exist -NE $true | 
       % {$_.Val.Row | out-file "c:\temp\test\New.txt" -Append} 
+0

嗨,這很好,但是當我運行代碼它不起作用。我必須刪除第一行的文件。之後,它仍然給我一個錯誤。無法綁定參數'FilterScript'。無法將「System.String」類型的「Exist」值轉換爲鍵入「System.Management.Automation.ScriptBlock」。其中<<<< Exist -NE $ true。 .......它是一個PowerShell版本錯誤?再次感謝您的幫助! :D – Cesar

+0

你應該更新你的PowerShell版本;) – Esperento57

+0

或修改爲:其中{$ _。Exist -NE $ true} – Esperento57

0

好,而不是在$結果文件寫入的結果,它保存在一個變量$ tmpResult然後做對$ tmpResult和$ file3進行相同的檢查以獲得最終結果。如果您有超過3個文件,您可以創建一個循環來重複檢查。

但上面的代碼中缺少一些東西 - 你只能得到file2中的唯一行,而不是file1中的那些。

1
$file1 = ".\test1.txt" 
$file2 = ".\test2.txt" 
$file3 = ".\test3.txt" 
$results = ".\New.txt" 

$Content = Get-Content $File1 
$Content += Get-Content $File2 

Get-Content $file3 | Where {$Content -notcontains $_}| Set-Content $Results 
1

其他解決方案1 ​​

#get couple files/values 
$filesvalues=gci "C:\temp\test\test*.txt" -file | 
    %{$filename=$_.Name; gc $_ | 
     %{[pscustomobject]@{FileName= $filename; Row=$_ }}} 

#group by value and filter by number of distinct filename, then extract data into file 
($filesvalues | group -Property Row | where {($_.Group.FileName | Get-Unique).Count -eq 1 }).Group.Row | 
    out-file "C:\temp\test\New2.txt" -Append 
1

Compare-Object cmdlet的目的是比較組輸入。
嵌套 2個Compare-Object呼叫產生所需的輸出:

$file1Lines = Get-Content .\test1.txt 
$file2Lines = Get-Content .\test2.txt 
$file3Lines = Get-Content .\test3.txt 

(Compare-Object ` 
    (Compare-Object -IncludeEqual $file1Lines $file2Lines).InputObject ` 
    $file3Lines | 
    Where-Object SideIndicator -eq '=>' 
).InputObject 
  • Compare-Object輸出[pscustomobject]實例,其.InputObject屬性包含所述輸入物體和其.SideIndicator屬性指示該操作數中的值是唯一的 - <=(LHS )或>=(RHS) - 和-IncludeEqual,如果它包含在兩個操作數(==)。

  • 第一Compare-Object呼叫-IncludeEqual不僅輸出用於不同的線路,但也包括那些是相同,導致線的聯合從文件test1.txttest2.txt

  • 通過指定用於所述第二Compare-Object呼叫開關,只有[對象包裝]爲不同線是輸出(默認行爲)。

  • 過濾器Where-Object SideIndicator -eq '=>'然後將差異過濾到RHS特有的那些行。


概括命令N> 3個文件並輸出到一個新的文件:

# Get all input files as file objects. 
$files = Get-ChildItem .\test*.txt 

# I'll asume that all files but the last are the *reference files* - the 
# files for which the union of all their lines should be formed first... 
$refFiles = $files[0..$($files.count-2)] 

# ... and that the last file is the *difference file* - the file whose lines 
# to compare against the union of lines from the reference files. 
$diffFile = $files[($files.count-1)] 

# The output file path. 
$results = ".\New.txt" 

# Build the union of all lines from the reference files. 
$unionOfLines = @() 
$refFiles | ForEach-Object { 
    $unionOfLines = (Compare-Object -IncludeEqual $unionOfLines (Get-Content $_)).InputObject 
} 

# Compare the union of lines to the difference file and 
# output only the lines unique to the difference file to the output file. 
(Compare-Object $unionOfLines (Get-Content $diffFile) | 
    Where-Object SideIndicator -eq '=>').InputObject | 
    Set-Content $results 

注意Set-Content在默認情況下使用Windows傳統的單字節編碼。使用-Encoding參數來更改該參數。

+0

完美!但讓我們說我有10個文本文件遵循與我的例子相同的邏輯,我將如何獲得前9個txt文件中不存在的行?感謝您的幫助!! :) – Cesar

+0

@Cesar:我的榮幸;請看我的更新爲通用N> 3解決方案。 – mklement0

相關問題