我们公司从第三方获取库存文件。这些文件采用固定格式,包含 13 位 EAN(类似 UPC 代码)以及其他数据。我们的数据库中还有 EAN 主列表。
我想将主文件与新文件进行比较,并从新文件中删除所有包含主文件中没有的 EAN 的行。
例如:主
1234567890123
4567890123456
新文件 1234567890123 4567890123456
5678901234567 <- 删除此文件
新文件包含 EAN 以外的数据。EAN 位于第一列。数据以制表符分隔。
我目前在 PHP 中执行此操作。问题是两个文件各有大约 400 万行,而我的脚本占用了大量内存。我目前将整个主列表加载到 RAM 中并执行 isset()。
是否有任何智能的 Linux 技巧/程序可以帮助我?
答案1
用更适合 grep 的方式重新表述这个问题,您想要打印与某个 EAN 主列表中的 EAN 匹配的所有行。
假设类似 EAN 的内容不会出现在 EAN 列以外的任何地方,请尝试:
- 从中提取所有 EAN
master
- 将 EAN 列表压缩到正则表达式中
- 将正则表达式输入到 egrep
假设 EAN 是第一列master
(并且主表包含其他列)
egrep "(`cat master | awk '{print $1}' | tr '\n' '\\|' | sed 's/|$//'`)" newfile
应该接近(awk
如果master
仅仅是一个 EAN 列表,你可以删除它;最后使用令人讨厌的 sed 来删除|
管道其余部分导致的尾随)
如果 EAN(或类似 EAN 的 13 位数字模式)出现在数据的其他位置,则上述内容会失效,并且需要更复杂的正则表达式来将搜索限制在特定列。
答案2
尝试这样的操作:
# Put each code in one line, and sort them
sed -e 's/\ /\n/g' new | sort > neweans
sed -e '/s\ /\n/g' master | sort > mastereans
# Diff them by columns, and delete from the list
# the new's that are not in master. Then, print them
diff -y neweans mastereans | grep -v "<" | awk '{print $1}'