如何查找具有相同两个字段的行并删除除其中一行之外的所有行

如何查找具有相同两个字段的行并删除除其中一行之外的所有行

我认为如果我把这个问题分成几个部分会更容易。

  1. 有没有办法找到第一个字段中具有相同值且最后一个字段中具有相同值的行? - 但不一定彼此相等?

线路:

  AAAAA stuff in between BBBBB
  AAAAA more stuff in the middle CCCCCC
  AAAAA even more cool stuff BBBBB

兴趣线:

  AAAAA stuff in between BBBBB
  AAAAA even more cool stuff BBBBB
  1. 有没有办法删除除具有相同第一个和最后一个字段重复的行之外的所有行?

前:

  AAAAA stuff in between BBBBB
  AAAAA more stuff in the middle CCCCCC
  AAAAA even more cool stuff BBBBB

后:

  AAAAA stuff in between BBBBB
  AAAAA more stuff in the middle CCCCCC

我可以稍微处理该文件以简化解决方案 - 例如设置固定数量的字段。

目前,该文件每行的字段数量不同,但第一个和最后一个字段很重要。

所有字段之间都有空格。

我已经搜索并找到了一些对 awk 的引用,但我找不到 awk 以这种方式使用多个字段的示例。

十分感谢。

答案1

GNU AWK

这是使用稍微修改的输入文件进行的测试运行:

bash-4.3$ $ awk '{v=sprintf("%s_%s",$1,$NF); if ( ! a[v]) print;   a[v]++;   }' input.txt 
bash: $: command not found
bash-4.3$ awk '{v=sprintf("%s_%s",$1,$NF); if ( ! a[v]) print;   a[v]++;   }' input.txt 
AAAAA stuff in between BBBBB
AA stuff AAABBBBB
AAAAA more stuff in the middle CCCCCC

bash-4.3$ cat input.txt
AAAAA stuff in between BBBBB
AA stuff AAABBBBB
AAAAA more stuff in the middle CCCCCC
AAAAA even more cool stuff BBBBB
AAAAA extra line CCCCCC

这是如何运作的:

  • 关键点:我们构建一个键值对数组,并根据是否已经有该键值对的数组项进行打印
  • key 是通过v=sprintf("%s_%s",$1,$NF)where 构造的,$NF是行中的最后一个字段;例如,对于第 1 行和第 3 行,键为AAAAABBBBB。值是一个整数,每次匹配时都会递增。
  • v对每一行执行变量和相应的检查if (!a[v]) print,仅当在数组中找不到值时才进行打印。
  • a[v]++无论我们是否打印,都会在每一行上执行

正如 Sundeep 在评论中指出的那样,同样的方法可以简化为:

bash-4.3$ awk '!seen[$1"_"$NF]++' input.txt
AAAAA stuff in between BBBBB
AA stuff AAABBBBB
AAAAA more stuff in the middle CCCCCC

相关内容