大型 CSV 文件中的高效搜索模式
Efficient search pattern in large CSV file
我最近问过。我收到了一些非常有用的答案,这是用户@anubhava 的答案,我发现它更直接、更优雅。为了清楚起见,我将重复原始问题的一些信息。
我有一个很大的 CSV 文件(大约 5GB)我需要确定 30 个类别(在 action_type
列中)并创建一个单独的文件,其中只有与每个类别匹配的行。
我的输入文件 dataset.csv
是这样的:
action,action_type, Result
up,1,stringA
down,1,strinB
left,2,stringC
我正在使用以下方法来获得我想要的结果(再次感谢@anubhava)。
awk -F, 'NR > 1{fn = "_dataset.csv"; print >> fn; close(fn)}' file
这按预期工作。但我发现它很慢。现在已经 运行 14 个小时了,根据输出文件与原始文件的大小相比,它甚至还不到整个过程的 20%。
我 运行 在 Windows 10 上使用 AMD Ryzen PRO 3500 200MHz、4 核、8 个逻辑处理器、16GB 内存和一个 SDD 驱动器。我正在使用 GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.0)
。我的 CPU 当前为 30%,内存为 51%。我在 运行 awk
里面 Cygwin64 Terminal
.
我很想听听一些关于如何提高速度的建议。据我所知,这不是容量问题。难道这是 Cygwin 内部的 运行 吗?有替代解决方案吗?我正在考虑 Silver Searcher,但无法完全锻炼如何做 awk
为我做的同样事情。
一如既往,我很感激任何建议。
有排序:
awk -F, 'NR > 1{if(!seen[]++ && fn) close(fn); if(fn = "_dataset.csv"; print >> fn}' < (sort -t, -nk2 dataset.csv)
或者用gawk(不限数量开启fd-s)
gawk -F, 'NR > 1{fn = "_dataset.csv"; print >> fn;}' dataset.csv
这是使用任何 awk 的正确方法:
$ tail -n +2 file | sort -t, -k2,2n |
awk -F, '!=p{close(out); out="_dataset.csv"; p=} {print > out}'
我说这是正确方法的原因是它不依赖于排序时数据值之前的 header 行的第二个字段,不需要 awk 来测试 NR > 1
对于每一行输入,不需要数组来存储 $2s 或任何其他值,并且一次只保持 1 个输出文件打开(一次打开的文件越多,awk 的速度越慢 运行 ,尤其是 gawk 一旦你超过了其他 awks 支持的打开文件的限制,因为 gawk 必须根据需要在后台启动 opening/closing 文件)。它也不需要您在 运行 之前清空现有的输出文件,它会自动执行此操作,并且它只对每个输出文件进行字符串连接以创建输出文件一次,而不是每行一次。
就像当前接受的答案一样,上面的 sort
可以重新排序具有相同 $2 值的输入行 - 添加 -s
如果这是不可取的并且你有 GNU 排序,你有其他排序需要用不同的 awk 命令替换 tail
并添加另一个排序参数。
我最近问过
我有一个很大的 CSV 文件(大约 5GB)我需要确定 30 个类别(在 action_type
列中)并创建一个单独的文件,其中只有与每个类别匹配的行。
我的输入文件 dataset.csv
是这样的:
action,action_type, Result
up,1,stringA
down,1,strinB
left,2,stringC
我正在使用以下方法来获得我想要的结果(再次感谢@anubhava)。
awk -F, 'NR > 1{fn = "_dataset.csv"; print >> fn; close(fn)}' file
这按预期工作。但我发现它很慢。现在已经 运行 14 个小时了,根据输出文件与原始文件的大小相比,它甚至还不到整个过程的 20%。
我 运行 在 Windows 10 上使用 AMD Ryzen PRO 3500 200MHz、4 核、8 个逻辑处理器、16GB 内存和一个 SDD 驱动器。我正在使用 GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.0)
。我的 CPU 当前为 30%,内存为 51%。我在 运行 awk
里面 Cygwin64 Terminal
.
我很想听听一些关于如何提高速度的建议。据我所知,这不是容量问题。难道这是 Cygwin 内部的 运行 吗?有替代解决方案吗?我正在考虑 Silver Searcher,但无法完全锻炼如何做 awk
为我做的同样事情。
一如既往,我很感激任何建议。
有排序:
awk -F, 'NR > 1{if(!seen[]++ && fn) close(fn); if(fn = "_dataset.csv"; print >> fn}' < (sort -t, -nk2 dataset.csv)
或者用gawk(不限数量开启fd-s)
gawk -F, 'NR > 1{fn = "_dataset.csv"; print >> fn;}' dataset.csv
这是使用任何 awk 的正确方法:
$ tail -n +2 file | sort -t, -k2,2n |
awk -F, '!=p{close(out); out="_dataset.csv"; p=} {print > out}'
我说这是正确方法的原因是它不依赖于排序时数据值之前的 header 行的第二个字段,不需要 awk 来测试 NR > 1
对于每一行输入,不需要数组来存储 $2s 或任何其他值,并且一次只保持 1 个输出文件打开(一次打开的文件越多,awk 的速度越慢 运行 ,尤其是 gawk 一旦你超过了其他 awks 支持的打开文件的限制,因为 gawk 必须根据需要在后台启动 opening/closing 文件)。它也不需要您在 运行 之前清空现有的输出文件,它会自动执行此操作,并且它只对每个输出文件进行字符串连接以创建输出文件一次,而不是每行一次。
就像当前接受的答案一样,上面的 sort
可以重新排序具有相同 $2 值的输入行 - 添加 -s
如果这是不可取的并且你有 GNU 排序,你有其他排序需要用不同的 awk 命令替换 tail
并添加另一个排序参数。