【问题标题】:Extract unique lines from two sets of text files从两组文本文件中提取唯一行
【发布时间】:2017-10-11 03:40:16
【问题描述】:

在 A: 和 B: 这两个目录中各有 1 个或多个 文本文件。目的是打印一个单个文本文件,其中包含所有行出现在A:中。

(每个文本文件最多可包含 200 万行。如果 A: 有 2 个或多个唯一行 [即,仅在 A:,不在 B:] 中彼此相同,则只有其中之一行需要在 unique.txt 输出中列出。顺序列表 [sort] 不重要。)

感谢Lieven Keersmaekers 下面的脚本(干净且快速)。然而,我似乎陷入了在 unique.txt 文件中被截断的行(在字符 120 处;或包装),而不是像它们一样打印 整个 唯一行 exactly存在于 A: 中。

compare -r $(gc C:\a\*.txt | sort -u) -d $(gc C:\b\*.txt | sort -u) | ? {$_.SideIndicator -eq '<='} | select inputobject | Out-File unique.txt

我试图用这些来获得完整的、展开的行,但没有成功:

Format-Table -Wrap -AutoSize |

我做错了什么? Windows cmd linePowerShell 都可以。

【问题讨论】:

  • 以下内容可能会让您入门:compare -r $(gc C:\temp\testfile1.txt | sort -u) -d $(gc C:\temp\testfile2.txt | sort -u) | ? {$_.SideIndicator -eq '&lt;='} | select inputobject
  • C:\a&gt;compare -r $(gc C:\a\1.txt | sort -u) -d $(gc C:\b\1.txt | sort -u) | ? {$_.SideIndicator -eq '&lt;='} | select inputobject - msg:`系统找不到指定的文件`windows cmd line。
  • 抱歉,Powershell。
  • 试试compare -r $(gc C:\a\*.txt | sort -u) -d $(gc C:\b\*.txt | sort -u) | ? {$_.SideIndicator -eq '&lt;='} | select -expand inputobject | Out-File unique.txt
  • 完成免责声明 ;)

标签: windows powershell text command-line compare


【解决方案1】:

使用sort -ubashcombine

combine <(sort -u a/* ) not <(sort -u b/*)

以上假设不需要重复的行,并且 Windows 文件系统安装在 Linux 机器上或可从 Linux 机器访问。

注意combine 不需要排序数据,它可以以任何给定顺序显示来自A:\* 的行,并返回未排序 输出,例如:

combine <(cat a/*) not <(cat b/*)

...但是如果A:\* 包含的给定行的重复项比B:\* 多,这将失去不显示重复行的属性。

【讨论】:

  • combine &lt;(sort -u C:/a/* ) not &lt;(sort -u C:/b/*) &gt; unique.txt 在命令行中尝试过,但出现错误“系统找不到指定的文件”。如问题所示,windows命令行或powershell。谢谢。
  • 文本文件位于C:\aC:\b。在 Windows 命令行中,我运行 C:\&gt;combine &lt;(cat a/*) not &lt;(cat b/*) &gt; unique.txt 并得到 The system cannot find the file specified. 我做错了什么?顺序不重要。
  • @user3026965,这个答案之所以存在,是因为 Q 的早期草稿(错误?)标记为 shell(与 Unix 兼容)而不是 powershell。 Windows 找不到 combine,因为它是一个 Linux 实用程序(在 moreutils 包中可用,但不适用于 Windows)。要使用此代码,最简单的方法是将两个目录放在网络共享上,然后将 mount them on a Linux box 放在其中运行 combine
  • 谢谢你并纠正。最初误用shell 而不是powershell。寻找本地/离线、windows 命令行/powershell 解决方案。
【解决方案2】:

以下内容可能会让您入门。

短版(使用别名)

compare -r $(gc C:\a\*.txt | sort -u) -d $(gc C:\b\*.txt | sort -u) | 
    ? {$_.SideIndicator -eq '<='} | 
    select -expand inputobject | 
    Out-File unique.txt

加长版

Compare-Object -ReferenceObject $(Get-Content C:\a\*.txt | Sort-Object -Unique) -DifferenceObject $(Get-Content C:\b\*.txt | Sort-Object -Unique) | 
    Where-Object {$PSItem.SideIndicator -eq '<='} | 
    Select-Object -ExpandProperty inputobject | 
    Out-File unique.txt

请注意,我无法摆脱与&lt;=的比较可以并且应该更好地处理但我无法轻易找到方法的感觉。

【讨论】:

    【解决方案3】:

    应该有点性能的最天真的解决方案应该是

    $inB = [system.collections.generic.HashSet[string]]::new([string[]](Get-Content B\* | select -unique))
    
    Get-Content A\* |
      Where-Object { ! $inB.Contains($_) } |
      Out-File onlyinA.txt
    

    但是,您需要为内存中 B 中所有文件的所有唯一行付费。解决这个问题的唯一方法(没有更复杂的东西)是批量过滤 A 中的行,并依次删除 B 中文件中的更多行。

    【讨论】:

    • $inB = [system.collections.generic.HashSet[string]]::new(Get-Content C:\b\* | select -unique) Get-Content C:\a\* | Where-Object { ! $inB.Contains($_) } | Out-File onlyinA.txt 出现 4 个错误:在 line:1 char:58;方法调用中缺少')';意外的令牌“获取内容”;意外的令牌')'。
    • 抱歉,现在应该修复了。
    • 谢谢。没有错误消息,但没有结果就挂了。 (文本文件中有 100K 行。)$inB = [system.collections.generic.HashSet[string]]::new([string[]](Get-Content C:\b\* | select -unique)) Get-Content C:\a\* | Where-Object { ! $inB.Contains($_) } | Out-File onlyinA.txt
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 2018-11-11
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    相关资源
    最近更新 更多