解析大量文件的高效方法
Efficient method to parse large number of files
我的传入数据将在 130GB - 300GB 范围内,其中包含 1000 个(可能是数百万个)大小为 2KB - 1MB 的小型 .txt
文件,位于单个文件夹中。我想有效地解析它们。
我正在查看以下选项(引用自 - 21209029]:
使用printf
+ xargs
(后面是egrep
& awk
文本处理)
printf '%s[=10=]' *.txt | xargs -0 cat | egrep -i -v 'pattern1|...|pattern8' | awk '{gsub(/"\t",",")}1' > all_in_1.out
使用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
使用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 和 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 扩展。
我的传入数据将在 130GB - 300GB 范围内,其中包含 1000 个(可能是数百万个)大小为 2KB - 1MB 的小型 .txt
文件,位于单个文件夹中。我想有效地解析它们。
我正在查看以下选项(引用自 - 21209029]:
使用
printf
+xargs
(后面是egrep
&awk
文本处理)printf '%s[=10=]' *.txt | xargs -0 cat | egrep -i -v 'pattern1|...|pattern8' | awk '{gsub(/"\t",",")}1' > all_in_1.out
使用
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
使用
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 和 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 扩展。