从巨大的txt.gz文件中选择/复制包含字符串的行的最快方法

时间:2018-06-18 18:57:51

标签: linux ubuntu awk sed grep

所以我有以下sed一个班轮:

sed -e '/^S|/d' -e '/^T|/d' -e '/^#D=/d' -e '/^##/d' -e 's/H|/,H|/g' -e 's/Q|/,,Q|/g' -e '1 i\,,,' sample_1.txt > sample_2.txt

我有很多行以:

开头
  • S|
  • T|
  • #D=
  • ##
  • H|
  • Q|

想法是复制以第一个四分之一开始的行 通过H| 替换,H|Q|(行的开头),,Q|(行的开头)

但现在我需要:

  • 尽可能以最快的方式使用(互联网建议(m)awk比sed更快)
  • 从.txt.gz文件中读取并将结果保存在.txt.gz文件中,如果可能的话,避免使用中间的un-zip / re-zip
实际上有几百个.txt.gz文件,每个大约约1GB,以这种方式处理(全部在同一个文件夹中)。是否有CLI方法在所有这些上并行运行代码(因此每个核心将被分配目录中的文件的子集)?

- 我使用linux --ubuntu

2 个答案:

答案 0 :(得分:2)

未经测试,但可能非常接近 GNU Parallel

首先制作输出目录,以免覆盖任何有价值的数据:

mkdir -p output

现在宣布一个函数执行一个文件并将其导出到子进程,以便 GNU Parallel 启动的作业可以找到它:

doit(){
    echo Processing $1
    gzcat "$1" | awk '
        /^[ST]\|/ || /^#D=/ || /^##/ {next}    # ignore lines starting S|, T| etc
        /^H\|/ {print ","}                     # prefix "H|" with ","
        /^Q\|/ {print ",,"}                    # prefix "Q|" with ",,"
        1                                      # print all other lines
    ' | gzip > output/"$1"
}
export -f doit

现在并行处理所有txt.gz个文件并显示进度条:

parallel --bar doit ::: *txt.gz

答案 1 :(得分:1)

你想到的是这样的吗?

#!/bin/bash

export LC_ALL=C

zcat sample_1.txt.gz | gawk '
$1 !~ /^([ST]\||#D=|##)/ {
    switch ($0) {
        case /^H\|/:
            print "," $0
            break
        case /^Q\|/:
            print ",," $0
            break
        default:
            print $0
    }
}' | gzip > sample_2.txt.gz

export LC_ALL=C告诉您的环境,您不会期望扩展字符,并且可以大大加快执行速度。 zcat扩展并将gz文件转储到stdout。这是通过管道传输到gawk,它会检查每行的第一部分是否与您在问题中的前四个字符分组不匹配。对于通过该测试的行,输出到stdout(按请求按摩)。当gawk执行时,其标准输出会被传送到gzip并写入.txt.gz文件。

可以将xargs-P-n开关一起使用来并行化您的处理,但我认为GNU parallel可能更容易使用。