使用两个分隔符从10GB CSV文件中剪切选定的数据

时间:2013-01-29 12:11:10

标签: bash sed awk grep

我有一个10GB的CSV文件,我正试图从中剪切选择输出。 目前我已经得到了以下内容,但由于它的大小,它消耗(方式)太多资源,所以我希望优化它。

#!/bin/bash
FILE=data.txt
FILEPATH=/home/user/

if [[ -z $1 ]]; then
        echo "No search parameter specified. Specify one when running this."
fi

echo "Searching $FILEPATH/$FILE for $1.. this may take a while."
echo ""

while IFS= read -r LINE;
        do
                # Grep for $1 and cut select columns
                grep $1 | cut -d"," -f7,9,15,16,19,22,23,24
        done

输入文件的示例行如下所示:

  

结果:key = value1,error = 0,command = SetOperator | SOURCE:   文件= /家庭/用户/日志/电流,起始日期= 20130128,

我想要做的是搜索文件中的任何值,并从找到结果的每一行返回(剪切版本)结果。
例如,搜索“20130128”应返回:

  

SetOperator,value1,20130128,

这意味着我需要同时处理命令和equals作为分隔符。

我已经环顾了SO(即this)并花了一些Google-fu,而我发现人们普遍认为“阅读”很慢并且没有针对像这样的大文件进行优化;我没有找到很多替代品。

您建议我使用什么?
谢谢!

2 个答案:

答案 0 :(得分:1)

你的命令如下:

while IFS= read -r LINE;
        do
                # Grep for $1 and cut select columns
                grep $1 | cut -d"," -f7,9,15,16,19,22,23,24
        done

永远不会终止,因为你没有在任何文件或管道上运行grep。

使用grep加上管道加切割代替那个循环,试试这个:

awk -v re="$1" 'BEGIN{FS=OFS=","} $0~re{print $7,$9,$15,$16,$19,$22,$23,$24}' "${FILEPATH}/${FILE}"

答案 1 :(得分:0)

我没有要测试的10GB文件,但是grep手册页显示了两个可能有用的选项:

  

- 行缓冲
      在输出上使用行缓冲。这可能会导致性能下降。

     

- MMAP
      如果可能,使用mmap(2)系统调用来读取输入,而不是默认的read(2)系统调用。在某些情况下,   --mmap产生   更好的性能。但是, - mmap可能会导致未定义的行为   (包括核心转储)如果输入文件收缩而grep是   操作,或者发生I / O错误。

行缓冲选项会使整个命令运行得慢,但是你会开始更快地得到结果,mmap可能很奇怪。

使用这些选项然后循环将是不必要的,如下所示:

grep --mmap "pattern" file | cut -d"," -f7,9,15,16,19,22,23,24

grep --line-buffered "pattern" file | cut -d"," -f7,9,15,16,19,22,23,24