解析大量文件的有效方法

时间:2018-10-06 04:45:56

标签: shell parsing rhel memory-efficient

我收到的数据将在130GB-300GB的范围内,其中在单个文件夹中包含1000个(也许是数百万个)小型.txt文件,大小为2KB-1MB。我想高效地解析它们。

我正在查看以下选项(引自-21209029]:

  1. 使用printf + xargs(随后是egrepawk文本处理)

    printf '%s\0' *.txt | xargs -0 cat | egrep -i -v 'pattern1|...|pattern8' | awk '{gsub(/"\t",",")}1' > all_in_1.out
    
  2. 使用find + cat(随后是egrepawk文本处理)

    find . -name \*.txt -exec cat {} > all_in_1.tmp \;
    cat all_in_1.tmp | egrep -i -v 'pattern1|...|pattern8' | awk '{gsub(/"\t",",")}1' > all_in_1.out
    
  3. 使用for循环

    for file in *.txt
    do
      cat "$file" | egrep -i -v 'pattern1|...|pattern8' | awk '{gsub(/"\t",",")}1' >> all_in_1.out
    done
    

以上哪一项是最有效的?有更好的方法吗?

还是完全不建议使用shell命令来处理这种数量的数据处理(我确实更喜欢使用shell方法)?

服务器具有RHEL 6.5 OS,具有32 GB内存和16核(@ 2.2GHz)。

1 个答案:

答案 0 :(得分:1)

方法1和3在Shell命令行上展开文件列表。这不适用于大量文件。如果文件分布在许多目录中(可能包含数百万个文件),则方法1和3也不起作用。

方法2复制所有数据,因此效率也不高。

您应该使用find并将文件名直接传递到egrep。使用-h选项可取消显示文件名前缀:

find . -name \*.txt -print0 \
 | xargs -0 egrep -i -v -h 'pattern1|...|pattern8' \
 | awk '{gsub(/"\t",",")}1' > all_in_1.out

xargs将自动依次顺序启动多个egrep进程,以避免在一次调用中超出命令行限制。

根据文件内容,完全避免egrep进程,而直接在awk中进行过滤也可能更有效:

find . -name \*.txt -print0 \
 | xargs -0 awk 'BEGIN { IGNORECASE = 1 } ! /pattern1|...|pattern8/ {gsub(/"\t",",")}1' > all_in_1.out

BEGIN { IGNORECASE = 1 }对应于-i的{​​{1}}选项,并且egrep颠倒了匹配的意义,就像!一样。 -v似乎是GNU扩展名。