我有两个文件 list.txt
和 purchaselist.txt
,它们相当大,我正在尝试获取最新的购买详细信息(purchaselist 中有重复项)。
假设以下是文件内容:
list.txt
1111
2222
3333
purchaselist.txt
0001 1111 210.00 abcd 10 A 151234 181234 ....
0011 1111 300.00 abcd 10 A 151000 181222 ....
0022 2222 110.00 abcd 10 E 151111 181000 ....
0099 2222 200.00 abcd 10 A 151222 181999 ....
0033 3333 110.00 abcd 10 A 151000 181222 ....
0044 0044 500.00 abcd 10 A 151999 181333 ....
8899 4444 800.00 abcd 10 A 153333 181777 ....
我使用 grep
和一个简单的 do while 循环来完成此操作。这是我的命令:
while read line; do tac purchaselist.txt | grep -m1 $line; done < list.txt >> result.txt
我的预期输出是,它已经看起来像这样:
0011 1111 300.00 abcd 10 A 151000 181222 ....
0099 2222 200.00 abcd 10 A 151222 181999 ....
0033 3333 110.00 abcd 10 A 151000 181222 ....
上面的输出是通过从我使用 tac
的 purchaselist.txt
文件中选取最新行得出的。 list.txt
中的值在 purchaselist.txt
中显示为第 18 列。这里的问题是文件很大。 list.txt
包含 580k 条记录,并在包含约 170 万条记录的 purchaselist.txt
中查找这些记录。上面的脚本已经运行了快20个小时了,还没有跑到一半。我如何优化这里的处理时间?
最佳答案
脚本速度很慢,因为对于 list.txt
中的每个单词您已阅读全文purchaselist.txt
,在您的情况下,它将被读取 580K 次。此外,bash 在大型迭代中运行速度并不快。
如果可以接受其他方法,可以使用 datamash
:
datamash -t ' ' -g 1 last 2 < purchaselist.txt
-
-t ' '
字段分隔符=空格 -
-g 1
按字段1分组 -
last 2
字段 2 的最后一个值
顺便说一句,4444
不在 list.txt
中但显示在最终输出中,所以我假设 list.txt
不需要。如果这是一个拼写错误,您可以使用 datamash -t ' ' -g 1 last 2 < purchaselist.txt | grep -f list.txt
.
此外,如果 datamash
尚未安装,您没有权限安装可以使用的软件包 awk
相反:
awk 'ARGIND==1{a[$0]}ARGIND==2{b[$1]=$2}END{for(i in a)if(i in b)print i,b[i]}' list.txt purchaselist.txt
该命令由三部分组成ARGIND == 1
ARGIND == 2
END
:
-
ARGIND == 1
表示参数索引 1(您可以将其视为argv[1]
、list.txt
) -
a[$0]
$0表示整行,放入字典中 -
b[$1] = $2
创建另一个字典存储每个项目($2
)的价格($1
,第二个字段),现有值以这种方式覆盖 -
END
处理完这两个文件后 -
for (i in a) if (i in b)
如果两者都在file.txt
和purchaselist.txt
-
print i,b[i]
打印键和值
编辑
对于非 GNU awk
,可以使用
awk 'NR==FNR{a[$0];next}{b[$1]=$2}END{for(i in a)if(i in b)print i,b[i]}' list.txt purchaselist.txt
编辑 好的...如果您有多个字段:
tac purchaselist.txt | sort -suk2,2 | grep -f list.txt
-
tac
让最新的优先 -
-s
稳定排序以保持原始顺序 -
-u
采取独特的-k2,2
(第二个字段)即只保留特定键值的第一条记录 -
-k2,2
使用 2 到 2 的字段作为键 -
grep
过滤掉不需要的项目
关于linux - 优化大文件的 grep 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57734888/