在未排序列上使用awk(或任何其他unix命令)连接两个以上的文件

x33g5p2x  于 2021-06-24  发布在  Hive
关注(0)|答案(1)|浏览(354)

我有4个文件(比如a,b,c,d)和一列(mac地址)


**file A**

ej  
j8  
00  
5h  
fl  

**file B**

ej  
6o  
00  
jq  
j6  

**file C**

ej  
85  
54  
5e  
f9  

**file D**

ej  
j8  
70  
5e  
70

其中文件a是我的主文件。
来自a的mac地址不应出现在任何其他文件b、c和d中:
如果有,就把它取下来。
或者我们可以创建一个新的列,其中的“y”/“n”标志值表示是否存在。

  • 请注意,此列无法排序。

预期产量:

5h
fl

如果您可以包含一个方法来指定文件的列号(如果存在多个列),那就太好了。

k75qkfdt

k75qkfdt1#

我的建议是这样的:

awk '(NR==FNR){a[$1]=$0;next}
     ($1 in a){delete a[$1]}
     END{for(i in a) print a[i]}' file_a file_b file_c ...

这里我们假设所有文件中的密钥都是 $1 (即mac地址)。代码的工作方式如下: (NR==FNR){a[$1]=$0;next} :读取第一个文件(文件a)时,将其记录/行存储在由字段1中的mac地址索引的数组中。使用 next 跳过任何进一步的处理并移到下一个记录/行。 ($1 in a){delete a[$1]} :对于任何其他文件,请检查密钥(mac地址)是否是数组a的一部分。如果是,这意味着我们可以从数组中删除它,因为我们对它不感兴趣。 END{for(i in a) print a[i]} :最后,处理完所有文件后,检查阵列中仍有哪些mac地址可用。这意味着这些数组位于文件a中,但不在任何其他文件中。打印出来(请注意,它们不会按文件a的顺序打印)
如果 $1 并不总是关键,但每行的某个地方都有一个mac地址,我们可以使用正则表达式来获取它:

awk 'BEGIN{ere_mac = "[0-9A-Fa-f][0-9A-Fa-f][-:]"
           ere_mac = ere_mac ere_mac ere_mac ere_mac ere_mac;
           ere_mac = ere_mac "[0-9A-Fa-f][0-9A-Fa-f]"}
     { match($0,ere_mac); key=substr($0,RSTART,RLENGTH)}
     (NR==FNR) { a[key]=$0 }
     (key in a) { delete a[key] }
     END { for(i in a) print a[i] }' file_a file_b file_c ...

注意:这是一个非常复杂的构建方法 ere_mac ,但如果您的awk不接受分组和重复,那么它是有效的。否则使用 ere_mac=([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2}) 一个完整的替代和更简单的方法是:

grep -vFf <(awk '{print $1}' file_b file_c ...) file_a

相关问题