这个命令有点牛逼啊!
awk -F"\t" '{if (ARGIND == 1) list[$1]=9; else if (!($1 in fl)) print $0;}' filter.file source.file > result.file
awk命令的输入文件中,可以有多个文件,awk命令会逐个文件的处理
-F 指定了每行中字段的分隔符,这里是\t制表符
ARGIND 表示awk当前处理的文件的序号,如上输入有两个文件,当处理filter.file的时候,ARGIND=1,当处理source.file的时候ARGIND=2,依次类推
上述还定义了一个数组list
逻辑解释:
先说下两个文件的内容:
#cat filter.file
116463543
137131577
135902549
137131579
116463545
140603581
120976251
140603583
116463548
119775071
120976253
140603585
120976255
121164581
119775073
140603587
120976257
121164583
119775075
120123880
这个文件其实都是搜狗百科的一些词条的id
#cat source.file
1084 6 我(我) 119 2016-04-07 20:44:24 138736601
1208 6 雅诗兰黛(护肤品) 38 2016-10-10 19:03:20 154931627
1254 6 三聚氰胺 29 2016-09-07 22:01:28 153184177
1310 6 奥林匹克 7 2015-02-13 16:58:27 96921809
1312 6 珠穆朗玛峰(世界第一高峰) 82 2016-05-20 19:59:27 144842284
1356 6 开心网 31 2016-10-17 14:36:53 155160146
1359 6 侏儒黑猩猩 5 2015-07-15 22:17:59 102291783
1361 6 寰宇地理 17 2016-10-21 18:56:04 155422821
1363 6 探索·发现 13 2016-09-08 01:55:27 153468163
1365 6 火花游戏 15 2016-08-03 21:37:06 150499567
1367 6 狐狸啊,你在干什么呢 5 2013-08-26 12:27:36 61553011
1369 6 遇见完美邻居的方法 15 2016-07-31 17:23:36 149889646
1371 6 里卡多·伊泽克森·多斯·桑托斯·雷特(球星) 185 2016-08-16 18:19:10 152567286
1373 6 舍甫琴科(球星) 13 2016-10-12 13:25:16 155049105
1377 6 保罗·马尔蒂尼 29 2016-09-22 10:55:48 154468755
1379 6 阿尔贝托·吉拉迪诺(足球) 31 2016-08-13 07:55:24 152015114
这个文件里面是一些待处理的文本,以\t 制表符分割
awk先处理第一个文件filter.file,所以读取这个文件的每行的时候,因为ARGIND=1都成立,所以会将filter.file中每行的数据切分后的第一个字段(实际就是那些词条id),在数组中设置标志,比如list[140603585]=9,这里其实就是设置一个标记,表示这个id在第一个文件中存在,用来对第二个文件source.file进行过滤的
当处理第二个文件source.file的时候,每次读取一行文件,切分后的$1也是词条id,else if(!($1 in list)) 则是判断这个切分出来的id是否在数组中,如果不在,则打印print $0,就是打印出第二个文件整行的内容。
所以命令实现的功能就是: 将source.file文件中id不在filter.file中的数据行过滤出来
注意:有的时候会发现这样的过滤死活不起作用
原因分析:
两个文件可能是从DOS下传到Unix系统上的,由于DOS下文件的换行符是\r\n, 但是Unix是\n, 所以导致,Unix里面将\r作为了每行内容的一部分,导致匹配不上
解决办法:针对两个文件分别执行如下命令将DOS文件转成UNIx文件
# dos2unix file1
# dos2unix file2