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