今天遇到一个比较tricky的问题,问题如下:
假设有两个文件f1,f2,f1中有两列a,b。f2中有多列,但是包含了a和b。现在想要从f2中查找出f1中对应的记录。
先post下我最终的解决方案吧:
cat f1 | while read line; do s=($line); a=${s[0]}; b=${s[1]}; awk -v a=$a -v b=$b '{if ($1==a && $5==b) print $0}' f2; done
这段代码其实很简单,读出f1,装入数组,用awk来查询。主要走了一些弯路,记录下一些用法和区别:
首先我是想用最简单的办法,for和grep组合来做,大概思路如下:
for line in $(cat f1); do s=($line); a=${s[0]}; b=${s[1]}; grep $a f2 | grep $b; done
这就有一个问题,我们要实现的目的是读出每一行,把每一行的值赋给数组,但是for直接根据空格来遍历,而不是每一行来遍历,而while就没有这个问题,
刚开始我还想通过set IFS='\n'来强制按行遍历,但是数组赋值这时候又会出问题。
中间我还想通过python来实现,简单实现了下,但是效果不理想。大致代码如下:
f1 = open("f1.txt")
f2 = open("f2.txt")
for line in f2:
for l in f1:
content = l.split("\t")
if content[0] in line and content[1] in line:
print l
print line
f1.close()
f2.close()
这个循环有个问题,第二重循环f1遍历的时候,遍历完了就到end了,不会从头再次遍历,有两种办法:
第一,在遍历f1之前加个seek(0)
第二,直接把两个文件全部读入内存,赋值后再遍历就没有问题了。
update: 20180309
用while循环解决方案今天遇到一个坑,用管道符'|'其实是启动一个子进程,所以如果子进程改变父进程的变量,这种方式是不可行的,那如果文件行中有空格又想用for循环,解决办法是cat后再awk下就没问题了,当然对于以上问题,awk是没用的。
网友评论