【问题标题】:Efficient method to parse large number of files解析大量文件的有效方法
【发布时间】:2019-03-11 13:28:47
【问题描述】:

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

我正在研究以下选项(来自 - 21209029]:

  1. 使用printf + xargs(后跟egrep & awk 文本处理)

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

    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 操作系统和 32 GB 内存和 16 个内核 (@2.2GHz)。

【问题讨论】:

  • 您是否有理由无法测试这些不同的方法以确定哪种方法最适合您的需求?
  • @KenWhite ,我将测试这些方法以检查其中最有效的方法,我只是想知道是否有更好的方法。

标签: shell parsing rhel memory-efficient


【解决方案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 }对应egrep的-i选项,!反转匹配的意义,就像-v一样。 IGNORECASE 似乎是 GNU 扩展。

【讨论】:

  • 感谢您的回答,我已经编辑了我的问题以声明所有文件都将驻留在一个文件夹中。
  • 老实说,这似乎不太可能:文件大小最多为 1 MiB,总大小至少为 130 GiB,您在一个目录中查看的文件至少为 130,000 个,甚至可能更多。这会给文件系统带来很多的压力。但是,我的答案没有任何变化。命令行长度限制的问题依然存在。
猜你喜欢
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-23
  • 2010-11-03
  • 2011-01-21
  • 2012-05-28
  • 1970-01-01
相关资源
最近更新 更多