我有两个文件。其中一个是包含 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
如何:
- 将字段分隔符设置为
,
当
FNR=NR
第一个文件正在处理时。在本例中,将 vin 编号读入值为 1 的关联中。然后next
跳过其余代码对于第一个文件之后的所有文件,如果记录号 9(vin)不在关联数组中,则打印该行。
答案4
grep
足以完成此任务:
grep -vFf vinlist data.csv
但是,在您的示例文本中,vinlist 中有尾随空格,因此要将其删除:(假设 bash 或其他具有进程替换语法的 shell)
grep -vFf <(sed -r 's/^[[:blank:]]+|[[:blank:]]+$//g' vinlist) data.csv