繁体   English   中英

使用awk删除基于两个字段的文件中的冗余

[英]remove redundancy in a file based on two fields, using awk

我试图根据前两列的值删除一个非常大的文件(约100,000条记录)中的重复行,而不考虑它们的顺序,然后打印这些字段和其他列。

因此,从此输入:

A B XX XX
A C XX XX
B A XX XX
B D XX XX
B E XX XX
C A XX XX

我想拥有:

A B XX XX
A C XX XX
B D XX XX
B E XX XX

(也就是说,我要删除“ BA”和“ CA”,因为它们已经以相反的顺序出现;我不在乎下一列中的内容,但我也想打印它)

我的印象是,使用awk +数组应该很容易,但是我无法提供解决方案。

到目前为止,我正在对此进行修改:

awk '
NR == FNR {
h[$1] = $2   
next
}
$1 in h {
print h[$1],$2}' input.txt

我将第二列存储在由第一列(h)索引的数组中,然后检查存储的数组中是否存在第一字段。 然后,打印该行。 但是出了点问题,我没有输出。

很抱歉,因为我的代码根本没有帮助,但是我对此有些犹豫。

你有什么想法?

非常感谢!

只需跟踪两种格式上出现的内容即可:

$ awk '!seen[$1,$2]++ && !seen[$2,$1]++' file
A B XX XX
A C XX XX
B D XX XX
B E XX XX

相当于awk '!(seen[$1,$2]++ || seen[$2,$1]++)' file

请注意,这也等同于没有第二个表达式++ (请参见注释):

awk '!seen[$1,$2]++ && !seen[$2,$1]' file

说明

打印唯一行的典型方法是:

awk '!seen[$0]++' file

这将创建一个seeed seen[]数组,其索引是到目前为止已出现的行。 因此,如果它是新的,则seen[$0]为0,并递增为1。但是以前,它是打印的,因为表达式! var ++ ! var ++评估! var ! var first(在awk ,True触发打印当前行的操作)。 如果已经看到该行,则seen[$0]具有正值,因此!seen[$0]为false,不会触发打印操作。

在您的情况下,无论顺序如何,您都希望跟踪出现的内容,所以我要做的是将索引存储在两个可能的位置。

使用如下

$awk '{if( $1$2 in a == 0 && $2$1 in a == 0 ) a[$1$2]=$0; } END{ for(i in a)print a[i]; }' input.txt

说明:命令正在使用数组键将记录存储在数组(a)中,因为数组中没有第一字段和第二字段的组合(即$ 1 $ 2和$ 2 $ 1)。 读取完整文件后,请打印阵列(a)。

# ($1$2 in a) => checks if there is any key with $1$2 in array a
# if it's not present then it return 0 
# and if both combination $1$2 and $2$1 are not present then store the record in array a
if( $1$2 in a == 0 && $2$1 in a == 0 ) a[$1$2]=$0;

# below print the array a (which stores complete unique record) at the end 
END{ for(i in a) print a[i]; }'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM