我有一个包含60210行的大csv文件。这些行包含散列、路径和文件名,如下所示:
hash | path | number | hash-2 | name
459asde2c6a221f6... | folder/..| 6 | 1a484efd6.. | file.txt
777abeef659a481f... | folder/..| 1 | 00ab89e6f.. | anotherfile.txt
....我正在过滤有关散列列表的文件,为了简化过滤过程,我创建并使用了该文件的简化版本,如下所示:
hash | path
459asde2c6a221f6... | folder/..
777abeef659a481f... | folder/..过滤后的结果包含了在我的引用哈希基中不存在的所有具有散列的行。
但是为了对过滤结果进行正确的分析,我需要删除之前的数据。因此,我的想法是读取过滤的结果文件,搜索hash字段,并将其写入将包含所有数据的增强结果文件中。
我使用一个循环来做到这一点:
getRealNames() {
originalcontent="$( cat $originalfile)"
while IFS='' read -r line; do
hash=$( echo "$line" | cut -f 1 -d " " )
originalline=$( echo "$originalcontent" |grep "$hash" )
if [ ! -z "$originalline" ]; then
echo "$originalline" > "$resultenhanced"
fi
done < "$resultfile"
}但在实际使用中,效率很低:对于之前的文件,这个循环在4Go RAM、Intel Centrino 2系统上运行大约需要3个小时,在我看来,对这种操作来说太长了。
有什么办法可以改进这个手术吗?
发布于 2018-10-17 09:59:45
考虑到问题的本质,我们很难理解为什么您会更喜欢使用shell来处理如此庞大的文件,比如awk或sed来处理它们。正如Stéphane Chazelas在Unix.SE的精彩答案中所指出的。
一旦您使用awk/perl来加速文本处理,您的问题就很容易解决。而且,您正在通过执行originalcontent="$( cat $originalfile)"将整个文件消耗到内存中,这一点都不可取。
假设在原始文件和引用文件中,hash从第一列开始,列由|分隔,则需要将awk用作
awk -v FS="|" 'FNR==NR{ uniqueHash[$1]; next }!($1 in uniqueHash)' ref_file orig_file上述尝试只将引用文件中的第一列条目输入内存,根本不使用原始文件。一旦我们使用了引用文件的$1 (第一列)中的条目,就可以通过选择那些不在我们创建的数组(uniqueHash)中的行对原始文件进行筛选。
通过将locale区域设置设置为LC_ALL=C awk ...,更改您的C设置,使其更快
发布于 2018-10-17 10:39:55
您对试图做什么的解释不明确,因为它描述了两个任务:过滤数据,然后将缺失的值添加回筛选后的数据。您的示例脚本解决了第二个问题,所以我假设这就是您在这里试图解决的问题。
在我阅读时,您有一个包含散列和路径的筛选结果,您需要在原始文件中查找这些散列以获得其他字段值。与其将原始文件加载到内存中,不如让grep直接处理该文件。假设一个空格(如cut -d " "所示)是您的字段分隔符,您也可以在read命令中提取哈希。
while IFS=' ' read -r hash data; do
grep "$hash" "$originalfile" >> "$resultenhanced"
done < "$resultfile"https://stackoverflow.com/questions/52851664
复制相似问题