【问题标题】:Cut selected data from 10GB CSV file with two delimiters使用两个分隔符从 10GB CSV 文件中剪切选定的数据
【发布时间】:2013-01-13 00:06:16
【问题描述】:

我有一个 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: 文件=/home/user/logs/current,start_date=20130128,

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

SetOperator,value1,20130128,

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

我查看了 SO(即this)并使用了一些 Google-fu,虽然我发现普遍认为“读取”速度很慢并且没有针对诸如此类的大文件进行优化;我没有找到很多替代方案。

你会推荐我用什么?
谢谢!

【问题讨论】:

  • 你能简单地做grep "$1" "$FILEPATH/$FILE" | cut -d"," -f7,9,15,16,19,22,23,24吗?除非我误解了你,否则不需要循环 bash 中的行...
  • 我可以,但是由于文件的大小,需要> 10分钟才能找到任何东西。理想情况下,我希望将其缩短到
  • 你的瓶颈是CPU还是I/O?哪个进程是导致瓶颈的进程,grep 还是 cut?
  • 我看不到您在哪里使用为您的阅读而声明的 LINE 变量。唯一比 grep 文件更快的方法是将其拆分并执行多个 grep,但当然,拆分时您必须读取文件并写入文件(这需要更长的时间)。或者您可以查看一个为并行处理而设计的系统,例如 hadoop,但只有在您多次执行此操作时才会有所帮助。最后,如果这是一个前进的项目,请考虑更改流程以创建可以并行处理而无需预处理的较小文件。祝你好运。 (重新考虑你的问题;-)

标签: bash sed awk grep


【解决方案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 加上管道加上 cut 的循环,试试这个:

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

【讨论】:

    【解决方案2】:

    我没有要测试的 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-11
      • 2022-01-05
      • 2022-01-11
      • 1970-01-01
      • 2022-01-26
      • 1970-01-01
      • 2019-08-29
      • 2013-11-18
      相关资源
      最近更新 更多