我试图根据前两列的值删除一个非常大的文件(~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
Run Code Online (Sandbox Code Playgroud)
我想要:
A B XX XX
A C XX XX
B D XX XX
B E XX XX
Run Code Online (Sandbox Code Playgroud)
(也就是说,我想删除“BA”和“CA”,因为它们已经以相反的顺序出现;我不关心下一列中的内容,但我也想打印它)
我的印象是使用 awk + 数组应该很容易做到这一点,但我无法提出解决方案。
到目前为止,我正在修补这个:
awk '
NR == FNR {
h[$1] = $2
next
}
$1 in h {
print h[$1],$2}' input.txt
Run Code Online (Sandbox Code Playgroud)
我将第二列存储在由第一个 (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
Run Code Online (Sandbox Code Playgroud)
这相当于awk '!(seen[$1,$2]++ || seen[$2,$1]++)' file.
请注意,它也相当于没有++第二个表达式(见评论):
awk '!seen[$1,$2]++ && !seen[$2,$1]' file
Run Code Online (Sandbox Code Playgroud)
打印独特线条的典型方法是:
awk '!seen[$0]++' file
Run Code Online (Sandbox Code Playgroud)
这将创建一个数组,seen[]其索引是到目前为止出现的行。因此,如果它是新的,seen[$0]则为 0 并增加到 1。但之前它被打印,因为表达式首先! var ++计算! var(并且在awk, True 触发打印当前行的操作)。当已经看到该行时,seen[$0]它具有正值,因此!seen[$0]为 false 并且不会触发打印操作。
在您的情况下,您想跟踪出现的内容,无论顺序如何,所以我正在做的是将索引存储在两个可能的位置。