2016-12-14 78 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

相关问题