【问题标题】:Iterate through txt files and find rows that are not in all files遍历txt文件并找到不在所有文件中的行
【发布时间】:2016-12-14 21:09:20
【问题描述】:

我有一个包含 3 个文本文件的文件夹。 文件 1,称之为 test1.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

【问题讨论】:

    标签: shell powershell


    【解决方案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} 
    

    【讨论】:

    • 嗨,这很好,但是当我运行代码时它不起作用。我不得不删除你在第一行的文件。之后,它仍然给我一个错误。无法绑定参数“FilterScript”。无法将“System.String”类型的“Exist”值转换为“System.Management.Automation.ScriptBlock”类型。其中
    • 或修改为: where {$_.Exist -NE $true }
    • 是的,我有 1.0 版 :( 似乎 Exist = $filevalues.Where({.... 也必须更改。因为它给了我一个错误“方法调用失败,因为 [系统.Object[]] 不包含名为 'Where' 的方法。"
    • 尝试 Where-object 代替 where
    【解决方案2】:
    $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
    

    【讨论】:

      【解决方案3】:

      其他解决方案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
      

      【讨论】:

        【解决方案4】:

        Compare-Object cmdlet 的目的是比较两组 输入。
        嵌套两个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 属性指示该值对于哪个操作数是唯一的 - &lt;= (LHS) 或 &gt;= (RHS ) - 和-IncludeEqual,如果它包含在两个操作数中(==)。

        • -IncludeEqual in the 1st Compare-Object 调用不仅输出不同的行,还包括相同的行,导致文件test1.txttest2.txt 中的行联合

        • 通过 not2nd Compare-Object 调用指定开关,只有 [objects wrapping] differ 的行被输出(默认行为)。

        • 过滤 Where-Object SideIndicator -eq '=&gt;' 然后将差异过滤到 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 参数来改变它。

        【讨论】:

        • 完美!但是假设我有 10 个文本文件,其逻辑与我的示例相同。我怎样才能只得到前 9 个 txt 文件中不存在的行?谢谢你的帮助!! :)
        • @Cesar:我的荣幸;请参阅我的更新以获得通用 N > 3 解决方案。
        【解决方案5】:

        好吧,不是将结果写入 $results 文件,而是将其保存在变量 $tmpResult 中,然后对 $tmpResult 和 $file3 进行与上述相同的检查以获得最终结果。如果你有超过 3 个文件,你可以创建一个循环来重复检查。

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

        【讨论】:

          猜你喜欢
          • 2019-08-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-18
          • 1970-01-01
          • 2019-05-05
          • 2013-12-25
          • 2022-10-24
          相关资源
          最近更新 更多