选择一个文件中不包含另一个文件中的值的行

选择一个文件中不包含另一个文件中的值的行

我有两个文件。其中一个是包含 60490 行数据的 CSV。每行都是一组值,例如客户姓名、服务日期等。

第一个文件中的这些值之一是 VIN 值。

我有第二个大文件,其中包含 92809 VIN 的列表。

我需要找到一种方法来删除第一个文件中所有在第二个文件中列出 VIN 的行。

我已经尝试过下面的 grep 。这确实达到了我的预期,但它也非常慢,并且在输出大约 50 行后被操作系统杀死。

$ grep -v -f vinlist data.csv > output.csv

实现这一目标最快的方法是什么?我在研究时发现的所有内容似乎都需要完全排序的数据,两个文件中的行相同或需要很长时间/被操作系统杀死

数据.csv

123,[email protected],JOE,BLOGGS,123456789,12345-123,"Place Name",12345,1C4NJPBB4DD122174,2014-01-20  
123,[email protected],JOE,BLOGGS,123456789,12345-123,"Place Name",12345,1GMDV33179D147281,2014-01-20  
123,[email protected],JOE,BLOGGS,123456789,12345-123,"Place Name",12345,1FUYDCYB7WP879651,2014-01-20  
123,[email protected],JOE,BLOGGS,123456789,12345-123,"Place Name",12345,1FM5K8D8XFGA82149,2014-01-20  
123,[email protected],JOE,BLOGGS,123456789,12345-123,"Place Name",12345,5TDBT48A72S003496,2014-01-20  

唱片列表:

JF1VA1E6XH9812361  
1HGCP26369A103521  
3N1CN7AP0CL810631  
5XYZK3AB7BG089758  
1FM5K8D8XFGA82149  
4S3BMBG61C3019520  
1FTNE24LX4HA22330  
1N4AL3AP8FC420210  
2GTEC19C491123429  
3N1CN7AP5FL944233  

答案1

因为我们知道 vin 在行中的位置,所以我们不需要进行一般搜索。相反,我们可以将 Vins 读入一个数据结构,该结构已建立索引以允许快速查找。

使用Python你可以这样做:

代码:

# read the vins into a set to allow fast lookup
with open('file3', 'rU') as f:
    vins = {vin.strip() for vin in f.readlines()}

# go through the data file one line at a time
with open('file2', 'rU') as f:
    for line in f.readlines():

        # get the vin in the line
        vin = line.split(',')[8]

        # if the vin is not in our set, print out the line
        if vin not in vins:
            print(line.strip())

结果:

123,[email protected],JOE,BLOGGS,123456789,12345-123,"Place Name",12345,1C4NJPBB4DD122174,2014-01-20
123,[email protected],JOE,BLOGGS,123456789,12345-123,"Place Name",12345,1GMDV33179D147281,2014-01-20
123,[email protected],JOE,BLOGGS,123456789,12345-123,"Place Name",12345,1FUYDCYB7WP879651,2014-01-20
123,[email protected],JOE,BLOGGS,123456789,12345-123,"Place Name",12345,5TDBT48A72S003496,2014-01-20

答案2

您可以使用unix命令cut来选择data.csv中的vin。然后使用 sort 和 uniq -d 查找两个文件中共同的 vins。

在bash中:

cut -d',' -f9 > vin_data
sort vin_data vinlist | uniq -d > vin_to_delete

然后,您可以使用 python 或您最喜欢的脚本语言来创建新文件。我的Python脚本。

f=open('data_vin_removed.csv','w')
v=[i.strip() for i in open('vin_to_delete')]
for i in open('data.csv'):
    if any([j in i for j in v]):
        continue
    else:
        f.write(i)
f.close() 

这将创建一个包含 data.csv 行的文件,该文件在 vinlist 中没有 vins。

答案3

使用awk

代码:

awk -F, 'FNR==NR{a[$1]=1;next} !a[$9] {print}' vin_file data_file

正如评论中所建议的,一种更有效的内存方式:

awk -F, 'FNR==NR{a[$1];next} (!($9 in a))' vin_file data_file

如何:

  1. 将字段分隔符设置为,
  2. FNR=NR第一个文件正在处理时。在本例中,将 vin 编号读入值为 1 的关联中。然后next跳过其余代码

  3. 对于第一个文件之后的所有文件,如果记录号 9(vin)不在关联数组中,则打印该行。

答案4

grep足以完成此任务:

grep -vFf vinlist data.csv

但是,在您的示例文本中,vinlist 中有尾随空格,因此要将其删除:(假设 bash 或其他具有进程替换语法的 shell)

grep -vFf <(sed -r 's/^[[:blank:]]+|[[:blank:]]+$//g' vinlist) data.csv

相关内容