为了账号安全,请及时绑定邮箱和手机立即绑定

带有 ID 数组的单个 zcat 多个提取

带有 ID 数组的单个 zcat 多个提取

慕斯709654 2022-12-06 14:59:33
我有很多 GB+ 大小的 gz 档案,由于磁盘空间原因我无法解压。每个存档都有一个特定的标识号(例如 test365.gz)和如下结构:         1    1    2 1##########                 Name:     ZINC000077407198@<TRIPOS>MOLECULE ZINC000077407198      none@<TRIPOS>ATOM      1 C1          5.7064    -2.3998   -12.0246 C.3        1  LIG1  -0.1500@<TRIPOS>BOND     1    1    2 1##########                 Name:     ZINC000099999999@<TRIPOS>MOLECULE ZINC000099999999      none@<TRIPOS>ATOM      1 C1         -2.0084    -5.2055   -12.9609 C.3        1  LIG1  -0.1500@<TRIPOS>BOND     1    1    2 1##########                 Name:     ZINC000077402345@<TRIPOS>MOLECULE ZINC000077402345     none@<TRIPOS>ATOM      1 C1          6.5657    -1.5531   -15.3414 C.3        1  LIG1  -0.1500@<TRIPOS>BOND     1    1    2 1##########                 Name:     ZINC000077407198@<TRIPOS>MOLECULE ZINC000077407198      none@<TRIPOS>ATOM      1 C1          3.6696    -1.8305   -14.6766 C.3        1  LIG1  -0.1500@<TRIPOS>BOND     1    1    2 1##########                 Name:     ZINC000012345678@<TRIPOS>MOLECULE ZINC000012345678      none@<TRIPOS>ATOM      1 C1          4.5368    -0.8182   -17.4314 C.3        1  LIG1  -0.1500@<TRIPOS>BOND     1    1    2 1##########                 Name:     ZINC000077407100@<TRIPOS>MOLECULE ZINC000077407100      none@<TRIPOS>ATOM      1 C1          1.4756    -2.2562   -14.0852 C.3        1  LIG1  -0.1500@<TRIPOS>BOND     1    1    2 1##########                 Name:     ZINC000077407198@<TRIPOS>MOLECULE ZINC000077407198      none@<TRIPOS>ATOM      1 C1          6.1712    -0.8991   -16.4096 C.3        1  LIG1  -0.1500@<TRIPOS>BOND     1    1    2 1##########                 Name:     ZINC000077407198@<TRIPOS>MOLECULE ZINC000077407198      none@<TRIPOS>ATOM哪个工作正常。如果 ZINC000077407100 有 N 个块,我会在 zcat 上提取 N 个块,并且不介意以 ##### 开头的行。问题是我需要为我想要的信息的 N 个标识符/ZINC_NUMBER 读取存档 N 次。这需要很多时间,因为我有数千个要提取。所以我想找到一种方法来传递一个数组或标识符列表/ZINC_NUMBER,以根据数组/列表中的标识符将 zcat 读数输出到几个不同的文件。换句话说,我想使用 zcat 进行单次读取并提取一组标识符的数据,而不仅仅是一个。
查看完整描述

2 回答

?
GCT1015

TA贡献1827条经验 获得超4个赞

每个 OP 的要求是处理大量数据(数百万行,数 GB 数据,以及需要检索大约 100 个项目的数据)。从技术上讲,可以使用现代 bash,但这不太可能表现良好。一个更好的脚本引擎会在这里做得更好。


此处介绍了可能的 bash/awk 解决方案。它将扫描每个引用的文件一次,并一次性提取所有选定的标签。请注意,“标签”列表将被扫描多次,但暗示它的大小是合理的


#! /bin/bash -uex

TAGS=data.txt


file_list=$(awk '{ print $1 }' < $TAGS | sort -u)


for f in $file_list ;

do

        gz_name=${f%/}.gz

        zcat $gz_name | awk -v F=$f '

        # Remember tags to retrieve

!DATA && $1 == F { tags[$2] = 1 }

        # OUT set to current output file, empty if item not selected

DATA && $1 == "##########" && $2 == "Name:" {

        OUT = tags[$3] ? $3 ".out" : "" ;

}

OUT { print >OUT }

' $TAGS DATA=1 -

done

不用说,可以使用 Python、Perl、Javascript 或您最喜欢的文本处理工具编写上述 5 行 awk 作业。使用示例数据集进行测试。


查看完整回答
反对 回复 2022-12-06
?
胡子哥哥

TA贡献1825条经验 获得超6个赞

似乎每个以 开头的条目##########总是有 6 行。在这种情况下,使用grep -A7而不是使用sed -n /##.../,/##.../p. 我想您只打印了后续标题,因为这样更容易(至少在使用时sed)。因此,我排除了此答案中的后续标头(grep -A6而不是grep -A7)。


grep可以给出要搜索的模式列表。这是通过-f选项完成的。模式列表可以从您的文件中生成。首先按存档名称(例如test365)分组,然后打印该存档的所有模式。在这里我们习惯awk这样做。空字节分隔每个存档的模式部分。


为了防止误报(并可能加快搜索速度),我们只搜索完整的行而不是子字符串。为了加快速度,我们设置了LC_ALL=C. 您可能还会发现它zgrep比zcat | grep.


以下脚本最多解压缩每个存档一次。


awk -v prefix='##########                 Name:     ' '

  {a[$1]=a[$1] "\n" prefix $2}

  END {for (k in a) print k a[k] "\0"}

' /path/to/your/list.txt |

while IFS=$'\n' read -r -d '' archive patterns; do

  LC_ALL=C zgrep -A6 -Fxf <(printf %s "$patterns") "${archive/\//.gz}"

  # TODO do something with the output for this archive

done

在上面的脚本中,我test365/从您的列表test365.gz自动转换为。我不知道你的目录结构。如果您需要不同的东西,请修改zgrep. $archive遍历您的(分组)列表的第一列(即,每个存档仅列出一次)。


从您的示例代码来看,您似乎想要为每个模式生成一个单独的文件。为此,将循环体从上方替换为


zgrep ... > /tmp/zincfound

while IFS= read -r pattern; do

    grep -A6 -Fx "$pattern" /tmp/zincfound > "${pattern##* }.out" 

done <<< "$patterns"

rm /tmp/zincfound


查看完整回答
反对 回复 2022-12-06
  • 2 回答
  • 0 关注
  • 130 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号