比较awk中两个文件的字段

Posted

技术标签:

【中文标题】比较awk中两个文件的字段【英文标题】:Comparing fields of two files in awk 【发布时间】:2014-12-25 04:53:47 【问题描述】:

我想比较两个文件的两个字段,如下:

比较文件一的第二个字段和文件二的第一个字段,打印匹配(即使匹配重复)以及文件一和二的所有列。

文件 1:

 G4   b45  3  4
 G4   b45  1  3
 G3   b23  2  2
 G3   b22  2  6
 G3   b22  2  4

文件 2:

 b45  a  b  c
 b64  d  e  f  
 b23  g  h  i
 b22  j  k  l
 b20  m  n  o     

输出:

 G4   b45  a  b  c  3  4
 G4   b45  a  b  c  1  3
 G3   b23  g  h  i  2  2
 G3   b22  j  k  l  2  6
 G3   b22  j  k  l  2  4

我已经使用关联数组通过以下 awk 命令进行了尝试:

awk 'FNR==NR array1[$2] = $1 ; arrayrest[$2] = substr($0, index($0, $2)); next($1 in array1) print array1[$1] "\t" $0 "\t" arrayrest[$1]' file1 file2

但是有两个问题:

    如果在我希望打印它们时重复匹配,它不会打印这些行。 它在输出中重复文件二的第一个字段。

我怎样才能使这个 awk 命令正常工作?提前致谢。

【问题讨论】:

你试过join吗? join -1 2 -2 1 <(sort f1) <(sort f2) 几乎给出了这个输出。 【参考方案1】:

不是您想要的完全准确的输出格式,而是正确的输出内容。

awk 'FNR==NRseen[$1]=$0; next ($2 in seen) $2=seen[$2]7' file2 file1

添加| column -t 以获得更一致的列间距。

【讨论】:

+1 知道我不是唯一一个使用右手食指 (7) 比左手小指 (1) 多得多的人:-D 不过也可能是 awk 'FNR==NR..($2 in seen) && $2=seen[$2]'跨度> @Kent 哈!这就是你这样做的原因吗?我采用它是因为我认为它使它看起来越来越“神奇”,这(希望)让人们问起它。 我把 OFS="\t" 放在了列之间。所以,为了确保我理解,你把第二个文件的第一列作为“seen”数组的键,作为它的值,你把第二个文件的所有列都给了它,对吗?然后检查第一个文件的第 2 列是否存在于“seen”数组的键中,如果存在,则打印整个文件,其第二列是第二个文件的第二列。那正确吗?现在,确实,7 对我来说是一个神奇的术语?可以的话请解释一下吗? @EtanReisner 是的,我左手小指最常用的按键是ESC,就在我键盘上的1 旁边。 @Kent 我回避使用这样的模式分配有两个原因。我被 0"" 和 awk 的结果咬了几次,考虑到这是错误的,因为我认为这对不熟悉 awk 的人来说更令人困惑。但在这种情况下你是对的,这看起来肯定会安全工作。【参考方案2】:

这对你来说应该简单明了:

awk 'NR==FNR n[$2]=$0 if ($1 in n) print n[$1],$2,$3,$4' file1 file2

【讨论】:

【参考方案3】:

小awk

awk 'x[$1]=$0$2=x[$2]' f2 f1

如果 $1 和 $2 可以包含相同的值

 awk 'x[$1]=$0FNR!=NR&&$2=x[$2]' f2 f1

输出

G4  b45  a  b  c 3 4
G4  b45  a  b  c 1 3
G3  b23  g  h  i 2 2
G3  b22  j  k  l 2 6
G3  b22  j  k  l 2 4

【讨论】:

聪明。但是,如果f2 的任何第二个字段与该文件中任何先前的第一个字段匹配,这将不起作用(我不知道该数据是否可能)。添加FNR==NRnext 可以解决这个问题。如果f2 中的任何一行只是0,它也会失败,但对于这个数据来说这似乎不太可能。 @EtanReisner 我使用的事实是 file1 的 $1 和 $2 不太可能包含相同的值(从样本来看)。此外,它们似乎在每个数字之前都有一个字符,因此 0 应该不是问题。显然,这不是一个非常通用的方法,您的方法会更适合更广泛的问题。 出于好奇,您选择ARGIND<2 而不是FNR==NR 作为那个守卫有什么原因吗?保护第二种模式(即ARGIND>=2&&$2=x[$2])不是更有意义吗?因为您要避免的是来自f2 打印而不是分配的一行。 @EtanReisner 不是特别不,只是觉得我会做与平时不同的事情。无论如何我已经更新了:)

以上是关于比较awk中两个文件的字段的主要内容,如果未能解决你的问题,请参考以下文章

使用 awk 比较两个文件

AWK 比较两个文件中的两列输出匹配行 - 匹配中缺少行

使用 awk 比较两个文件并打印不匹配的记录

使用awk比较两个不同文件中的两列

awk将同一行中的两个元素与正则表达式进行比较

两个文件中的AWK列匹配,打印不同的列