首页 > 解决方案 > 如何提取第一列中没有重复值的行?

问题描述

对于一些统计研究,我想分离第一列中重复值的数据。我使用 vim。

假设我的一部分数据是这样的:

Item_ID   Customer_ID
  123          200
  104          134
  734          500
  123          345
  764          347
  1000         235
  734          546

如您所见,有些行在第一列中具有相同的值,

我想生成两个单独的文件,其中一个只包含非重复值,另一个包含第一列值相等的行。

对于上面的例子,我想要这两个文件:第一个包含:

Item_ID   Customer_ID
  123          200
  734          500
  123          345
  734          546

第二个包含:

Item_ID   Customer_ID
  104          134
  764          347
  1000         235

有谁能够帮助我?

标签: awkvimduplicates

解决方案


我认为在这里 awk 会是一个更好的选择。

$ awk 'FNR == NR { seen[$1]++; next } seen[$1] == 1' input.txt input.txt > uniq.txt
$ awk 'FNR == NR { seen[$1]++; next } seen[$1] > 1' input.txt input.txt > dup.txt

更漂亮的 awk 代码版本:

FNR == NR {
    seen[$1]++;
    next
}
seen[$1] == 1

概述

我们循环遍历文本两次。通过两次向我们的 awk 脚本提供相同的文件,我们有效地循环了文本两次。第一次虽然循环计算了我们看到字段值的次数。第二次虽然循环仅输出字段值计数为 的记录1。对于重复行的情况,我们只输出字段值计数大于 1 的行。

awk 入门

awk循环遍历文本文件/输入中的行(或记录)并将每一行拆分为字段。$1对于第一个字段,$2第二个字段等。默认情况下,字段由空格分隔(可以配置)。

awk以 .的形式通过一系列规则运行每一行condition { action }。任何时候进行condition比赛action

打印行匹配的第一个字段的示例foo

awk '/foo/ { print $1 }` input.txt

细节的荣耀

让我们看看只找到第一个字段只出现一次的唯一行。

$ awk 'FNR == NR { seen[$1]++; next } seen[$1] == 1' input.txt input.txt > uniq.txt

更漂亮的版本以提高可读性:

FNR == NR {
    seen[$1]++;
    next
}
seen[$1] == 1
  • awk 'code' input > output- 运行code输入文件,input然后将输出重定向到文件,output
  • awk可以接受多个输入。例如awk 'code' input1.txt input2.txt
  • 使用相同的输入文件 ,input.txt两次循环输入两次
  • awk 'FNR == NR { code1; next } code2' file1 file2是一个常见的 awk 习惯用法,将运行code1file1运行code2file2
  • NR是当前记录(行)号。这在每条记录后递增
  • FNR是当前文件的记录号。例如FNR1在每个文件的第一行
  • next将停止执行任何更多操作并转到下一条记录/行
  • FNR == NR仅适用于第一个文件
  • $1是第一个字段的数据
  • seen[$1]++-seen是一个数组/字典,我们使用第一个字段 ,$1作为我们的键并增加值,以便我们可以得到一个计数
  • $0是整条线
  • print ...打印出给定的字段
  • print $0将打印出整行
  • 只是print简写print $0
  • condition { print $0 }可以短路到condition { print }哪个可以进一步短路到只是condition
  • seen[$1] == 1检查第一个字段的值是否等于1并打印该行

推荐阅读