使用选定的字符串逐行比较 bash 文件

使用选定的字符串逐行比较 bash 文件

假设我有两个文件 a.txt、b.txt

a.txt

87621   3bde   NDF
87621   2dfg   NDF
87621   cdef   NDF
87621   abcd   NDF

b.txt

93291   abcd   NDF
93291   2dfg   NDF
93291   adbf   NDF
93291   gdrg   NDF

我的脚本应该创建一个文件,通过匹配两个文件的第 2 列,并在新文件 c.txt 中创建一个具有匹配字符串的文件,如下所示

c.txt

2dfg
abcd

我尝试了几种方法,但没有成功,你能帮忙吗!

答案1

这将读取所有行a.txt并跟踪其第 2 列的所有值。然后读取b.txt并打印出第 2 列的任何重复值:

$ awk 'NR==FNR {seen[$2]=1; next} seen[$2]==1 {seen[$2]++; print $2}' a.txt b.txt
abcd
2dfg

awk命令可分为两部分。第一部分是:

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

awk首先测试处理的记录(行)总数 是否NR与此文件中处理的记录数 相同FNR。这仅适用于处理的第一个文件,a.txt在本例中为 。因此,对于 中的每一行,将键设置为第二列的值的a.txt关联数组设置为 的值。这将用于指示 中“看到”了列 2 的这个值。以下命令是 ,它指示跳过其余命令并获取下一个记录。seen$21a.txtnextawk

第二部分是:

seen[$2]==1 {seen[$2]++; print $2}

由于next上面第一部分中的命令,此部分仅由文件执行b.txt。此部分以测试开始:它检查此$2记录的列 2 值 是否以前出现过。如果 以前出现过一次,则执行括号中的命令。括号中的第一个命令seen[$2]++将 的值递增,seen以便我们永远不会再次处理列 2 的这个值。(因此,列 2 的重复值将被忽略。)第二个命令只是打印 以前在 中出现过的列 2 的值a.txt

如果我们可以相信第 2 列没有重复的值,那么可以使用更简单的脚本:

$ awk '{print $2}' a.txt b.txt | sort | uniq -d
2dfg
abcd

答案2

comm -12 <(awk '{print $2}' a.txt | sort) <(awk '{print $2}' b.txt | sort) > c.txt

解释

  • <(...)流程替代. 即 中的命令的输出(...)被替换并用作 的两个输入comm
  • awk '{print $2}' a.txt仅打印每行的第二个字段。
  • sort将准备输入的输出进行排序comm
  • comm比较两个已排序的文件。-12标志会隐藏每个文件所特有的行,而只打印公共行(man comm有关详细信息,请参阅)。

答案3

下面的 perl 单行命令可以完成这个工作:

perl -lane 'BEGIN{%h}$h{$ARGV."\n".$F[1]}++;END{foreach(keys(%h)){s/.*\n//;$f{$_}++};for(keys(%f)){print if$f{$_}>1}}' a.txt b.txt > c.txt

相关内容