如果你有一个500K列的文件,你需要逐个拉出每一列,当你从$ 1进展到$ 500K时,它需要更长更长的时间。除了做一个简单的{print $column_index}
之外,还有一种快速的方法吗?同一索引处的列将从两个文件中拉出并并置并放入单独的文件中。因此,awk
的工作是从file-1和file-2中提取一列,我可以使用paste
并列两列。以下示例仅适用于一个文件。
测试数据:
for i in $(seq 1 1 20000); do perl -e 'print "0.001\t"x500000 . "\n"'; done > file-big-1.txt
定时:
time awk '{print $1000}' file-big-1.txt > /dev/null
real 5m18.143s
user 1m19.506s
sys 0m57.417s
time awk '{print $450000}' file-big-1.txt > /dev/null
real 12m52.124s
user 9m22.182s
sys 0m52.987s
我有一个可行的解决方案,我将cut
两个文件放入5K列子集并处理子集,并且速度相当快。
我尚未实现的另一个解决方案是转置文件并处理行。但是,如果代码需要首先将所有数据加载到内存中,那么转置这样一个大文件可能相当棘手。
这只是一种好奇心,因为我可以处理拆分块。我只是觉得有一个更好的方法。
添加问题,有没有办法转置文件而不先将数据粘贴到数组中?
答案 0 :(得分:0)
我不知道您的列平均有多宽,但是以下sed
命令可以在大约20毫秒内轻松地将5000个左右的100个字符宽,空格分隔的列转换为单独的行:
sed 's/ /\
/g'
如果您的数据包含多行多列,那么我建议您为输入中的每个换行替换一些其他唯一记录分隔符(例如ASCII RS)。
如果您担心尝试一次读取整个非常宽的内存行,您也可以使用任何可以执行缓冲I / O(例如C)的语言编写一个非常简单的小型列到行拆分器;虽然如果我在任何类型的具有良好虚拟内存支持的系统上执行此操作,并且地址空间大于文件大小,那么我很想mmap()
整个文件,以便可以对待它作为一个数组,然后扫描它并在一个通道中用换行符替换每个列分隔符;从而避免所有read()
/ write()
缓冲和正则表达式解析无意义。