Разделить файл по шаблону на две последовательные строки

У меня есть файлы следующего формата:

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). Я не могу понять, как проверить обе последовательные строки, чтобы определить точку разделения.


person mirix    schedule 27.08.2011    source источник
comment
В awk вы можете использовать next и print ... > filename для выполнения задачи. Используйте глобальную переменную для просмотра предыдущей строки.   -  person n. 1.8e9-where's-my-share m.    schedule 27.08.2011
comment
Подойдет ли вам скрипт Python?   -  person Tom Zych    schedule 27.08.2011
comment
Конечно. Изначально я хотел избежать каких-либо внешних скриптов. Но это занимает больше времени, чем ожидалось, из-за многочисленных исключений, возникающих при синтаксическом анализе данных. Это моя первая серьезная попытка кодирования, и я уже написал 500 строк за несколько дней... Что мне сейчас нужно, так это выполнить работу как можно скорее, независимо от того, как.   -  person mirix    schedule 27.08.2011


Ответы (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()
person Tom Zych    schedule 27.08.2011
comment
Оно работает! Спасибо. Единственная проблема заключается в том, что когда я дублирую имена цепочек, он перезаписывает предыдущий файл новым. Это означает, что если у меня есть две цепочки с именем A, то файл file_A будет записан один раз, а затем перезаписан следующим вхождением. Мне нужно найти способ предотвратить это. Может быть, лучше всего добавить счетчик, чтобы я писал файл_A1, файл_B2, файлC3, файл_A4 и так далее... - person mirix; 27.08.2011
comment
@mirix: Хорошо, новая версия должна это делать. Я не проверял это. - person Tom Zych; 27.08.2011

Вот awk версия

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

Используйте FILENAME вместо file, чтобы создать файл с тем же именем.

person ghostdog74    schedule 27.08.2011
comment
Мне придется проводить больше времени с awk, он намного короче, чем мое решение. - person Tom Zych; 27.08.2011
comment
@Tom: На данный момент ваш скрипт Python продемонстрировал свою надежность на 100%, тогда как этот скрипт awk допускает некоторые ошибки в более сложных ситуациях, чем тот, который приведен в качестве примера. - person mirix; 28.08.2011
comment
@mirix, все дело в программировании, чувак. Учитывая любую ситуацию, мое решение awk можно точно настроить, чтобы оно соответствовало решению Python .... поскольку это просто синтаксический анализ файлов/текста. - person ghostdog74; 28.08.2011
comment
@ghostdog74; да, на самом деле причина, по которой ваш однострочный awk не работает, заключается в следующем (как объяснено в другом потоке): иногда при больших значениях во втором столбце между первым и вторым столбцами не остается места, поэтому из с точки зрения ости, это всего лишь один столбец, и поэтому 5-й столбец становится 4-м. В формате PDB каждое поле занимает фиксированную позицию, поэтому лучше указать конкретную позицию, а не использовать разделители. Можно ли указать диапазон в awk? Я имею в виду что-то вроде 22-25 долларов (с -F )? - person mirix; 28.08.2011