2015-11-28 108 views
2

我必须使用bash脚本处理文件夹中的大量txt文件。 每个文件都包含一行万元与他们的格式是这样的:使用bash处理大量数据

文件#1:

en ample_1 200 
it example_3 24 
ar example_5 500 
fr.b example_4 570 
fr.c example_2 39 
en.n bample_6 10 

文件#2:

de example_3 4 
uk.n example_5 50 
de.n example_4 70 
uk example_2 9 
en ample_1 79 
en.n bample_6 1 

...

我已经必须按“en”或“en.n”过滤,在第二列中找到重复出现的内容,然后求和第三列并得到如下所示的排序文件:

en ample_1 279 
en.n bample_6 11 

这里我的脚本:

#! /bin/bash 
clear 
BASEPATH=<base_path> 
FILES=<folder_with_files> 
TEMP_UNZIPPED="tmp" 
FINAL_RES="pg-1" 
#iterate each file in folder and apply grep 
INDEX=0 
DATE=$(date "+DATE: %d/%m/%y - TIME: %H:%M:%S") 
echo "$DATE" > log 
for i in ${BASEPATH}${FILES} 
do 
FILENAME="${i%.*}" 
if [ $INDEX = 0 ]; then 
    VAR=$(gunzip $i) 
    #-e -> multiple condition; -w exact word; -r grep recursively; -h remove file path 
    FILTER_EN=$(grep -e '^en.n\|^en ' $FILENAME > $FINAL_RES) 
    INDEX=1 
    #remove file to free space 
    rm $FILENAME 
else 
    VAR=$(gunzip $i) 
    FILTER_EN=$(grep -e '^en.n\|^en ' $FILENAME > $TEMP_UNZIPPED) 
    cat $TEMP_UNZIPPED >> $FINAL_RES 
    #AWK BLOCK 
    #create array a indexed with page title and adding frequency parameter as value. 
    #eg. a['ciao']=2 -> the second time I find "ciao", I sum previous value 2 with the new. This is why i use "+=" operator 
    #for each element in array I print i=page_title and array content such as frequency 
    PARSING=$(awk '{ page_title=$1" "$2; 
        frequency=$3; 
        array[page_title]+=frequency 
        }END{ 
        for (i in array){ 
         print i,array[i] | "sort -k2,2" 
        } 
        }' $FINAL_RES) 

    echo "$PARSING" > $FINAL_RES 
    #END AWK BLOCK 
    rm $FILENAME 
    rm $TEMP_UNZIPPED 
fi 
done 
mv $FINAL_RES $BASEPATH/06/01/ 
DATE=$(date "+DATE: %d/%m/%y - TIME: %H:%M:%S") 
echo "$DATE" >> log 

一切正常,但它需要一个很长很长的时间来执行。有谁知道如何得到相同的结果,用更少的时间和更少的代码行?

+0

'bash'是*不*用于处理*大*量的数据。如果数据足够大,值得花时间开发一些更高效的程序(可能是某种编译语言)。但是*您*需要衡量余额并估计时间。等待5分钟就可以了(但是等待5天,你的bash脚本完成花费2个小时编写C程序或Ocaml的时间) –

+0

此外,实际数据(兆字节或兆兆字节)有多大,多长时间一次它会改变,你等待脚本完成多久?你有什么编程技巧? –

回答

6

UNIX shell是一个可以操作文件和进程并将调用顺序调用到工具的环境。 UNIX的工具外壳调用处理文本是AWK所以只是用它:

$ awk '$1~/^en(\.n)?$/{tot[$1" "$2]+=$3} END{for (key in tot) print key, tot[key]}' file | sort 
en ample_1 279 
en.n bample_6 11 

你的脚本有太多的问题上表明你在shell编程初学者评论 - 拿到书的bash shell脚本食谱由克里斯约翰逊和有效的Awk编程,第4版,阿诺德罗宾斯。

+0

谢谢你的回答。是的,我是shell编程的新手。你在说什么问题?我必须在同一个文件夹中处理大量文件,看起来你的脚本只能处理其中的一个。我错了吗? –

+0

对不起,我的脚本中有太多的问题要列出来。如果你想让脚本处理多个文件,只需在命令行列出这些文件,例如'awk'脚本'file1 file2 ... fileN',显然你可以使用'file *'或其他任何你希望shell的构造展开文件名列表 –

+1

好的,谢谢。我会得到你建议我的书! –