【问题标题】:Split file according to patterns in two consecutive lines根据连续两行中的模式拆分文件
【发布时间】:2024-01-14 12:29:02
【问题描述】:

我有以下格式的文件:

ATOM   3736  CB  THR A 486      -6.552 153.891  -7.922  1.00115.15           C  
ATOM   3737  OG1 THR A 486      -6.756 154.842  -6.866  1.00114.94           O  
ATOM   3738  CG2 THR A 486      -7.867 153.727  -8.636  1.00115.11           C  
ATOM   3739  OXT THR A 486      -4.978 151.257  -9.140  1.00115.13           O  
HETATM10351  C1  NAG A 203      33.671  87.279  39.456  0.50 90.22           C  
HETATM10483  C1  NAG A 702      28.025 104.269 -27.569  0.50 92.75           C    
ATOM   3736  CB  THR B 486      -6.552  86.240   7.922  1.00115.15           C  
ATOM   3737  OG1 THR B 486      -6.756  85.289   6.866  1.00114.94           O  
ATOM   3738  CG2 THR B 486      -7.867  86.404   8.636  1.00115.11           C  
ATOM   3739  OXT THR B 486      -4.978  88.874   9.140  1.00115.13           O  
HETATM10351  C1  NAG B 203      33.671 152.852 -39.456  0.50 90.22           C  
HETATM10639  C2  FUC B 402     -48.168 162.221 -22.404  0.50103.03           C 

我想在以 HETATM* 开头的每一行之后拆分文件,但前提是下一行以 ATOM 开头。我希望将新文件命名为 $basename_$column,其中 $basename 是输入文件的基本名称,$column 是位置 22-23 的字符(在示例中为 A 或 B)。我无法弄清楚如何检查两条连续的线以确定分割点。

【问题讨论】:

  • 在 awk 中,您可以使用 nextprint ... > filename 来完成任务。使用全局变量查看 previous 行。
  • Python 脚本适合你吗?
  • 当然。最初,我想避免使用任何外部脚本。但是由于解析数据时遇到了许多异常,这比预期花费的时间更长。这是我第一次认真尝试编码,几天之内我已经写了 500 行......我现在需要的是无论如何尽快完成工作。

标签: bash sed split awk lines


【解决方案1】:

这是awk 版本

awk 'NR==1{n=$5}/HETATM/{f=1}f && /^ATOM/{n=$5;f=0}{print > "file"n".txt"}' file

使用FILENAME 而不是file 创建相同的文件名。

【讨论】:

  • 我将不得不花更多时间在 awk 上,它肯定比我的解决方案短很多。
  • @Tom :到目前为止,您的 python 脚本已被证明是 100% 可靠的,而这个 awk 脚本在比示例提供的更复杂的情况下会犯一些错误。
  • @mirix,这一切都在编程中。在任何情况下,我的 awk 解决方案都可以进行微调以匹配 Python 的 .... 因为它只是文件/文本解析..
  • @ghostdog74;是的,事实上,你的 awk 单行不工作的原因如下(如其他线程中所述):有时,第二列中的值很大,第一列和第二列之间没有空间,所以从从 awn 的角度来看,这只是一列,因此第 5 列变为第 4 列。在 PDB 格式中,每个字段都占据一个固定的位置,因此最好提供特定的位置而不是使用分隔符。是否可以在 awk 中指定范围?我的意思是 22-25 美元(带 -F "")?
【解决方案2】:

这是一个没有错误检查的简单 Python 解决方案。应该在 Python 2 或 3 中工作;更改第一行以匹配您的环境。不要将此作为良好编码风格的示例。

针对唯一文件名进行了编辑。

#!/usr/bin/env python2.4

import os.path
import sys

fname = sys.argv[1]
bname = os.path.basename(fname)

fin = open(fname)

fout = None
ct = 0

for line in fin:
    if line[:6] == 'HETATM':
        flag = True
    if (not fout) or (flag and line[:4] == 'ATOM'):
        if fout:
            fout.close()
        ct += 1
        fout = open(bname + '_' + line[21:22] + str(ct), 'w')
        flag = False
    fout.write(line)

fout.close()

【讨论】:

  • 有效!谢谢。唯一的问题是,当我有重复的链名时,它会用新的文件覆盖以前的文件。这意味着如果我有两个名为 A 的链,它将写入 file_A 一次,然后将在下一次出现时覆盖它。我需要想办法防止这种情况发生。也许最好的方法是添加一个计数器,以便我将写入 file_A1、file_B2、fileC3、file_A4 等等......
  • @mirix:好的,新版本应该这样做。我没有测试它。