Python:仅替换字符串中的一个匹配项

时间:2013-02-22 12:15:05

标签: python

我有一些示例数据:

ATOM    973  CG  ARG A  61     -21.593   8.884  69.770  1.00 25.13           C
ATOM    974  CD  ARG A  61     -21.610   7.433  69.314  1.00 23.44           C
ATOM    975  NE  ARG A  61     -21.047   7.452  67.937  1.00 12.13           N

我想通过添加偏移值来替换第6列和第6列,在上面的情况下它是308.

所以61 + 308 = 369,所以第6列中的61应该被369替换

我不能str.split()这行,因为行间距非常重要。

我尝试过尝试使用str.replace(),但第2列中的值也可以与第6列重叠

我确实尝试撤消该行并使用str.repalce(),但第7,8,9,10和11列中的值可能与要替换的str重叠。

到目前为止,我所拥有的丑陋代码(除了第7,8,9,10和/或11列中的值重叠之外,部分工作原理):

with open('2kqx.pdb', 'r') as inf, open('2kqx_renumbered.pdb', 'w') as outf:
    for line in inf:
        if line.startswith('ATOM'):
            segs = line.split()
            if segs[4] == 'A':
                offset = 308
                number = segs[5][::-1]
                replacement = str((int(segs[5])+offset))[::-1]
                print number[::-1],replacement
                line_rev = line[::-1]
                replaced_line = line_rev.replace(number,replacement,1)
                print line
                print replaced_line[::-1]
                outf.write(replaced_line[::-1])

上面的代码在下面生成了这个输出。正如你在第二行看到的那样,第6列没有改变,但在第7列中有所改变。我想通过反转字符串我可以绕过与第2列的潜在重叠,但我忘记了其他列而我真的不知道如何绕过它。

ATOM    973  CG  ARG A  369     -21.593   8.884  69.770  1.00 25.13           C
ATOM    974  CD  ARG A  61     -21.3690   7.433  69.314  1.00 23.44           C
ATOM    975  NE  ARG A  369     -21.047   7.452  67.937  1.00 12.13           N

2 个答案:

答案 0 :(得分:2)

data = """\
ATOM    973  CG  ARG A  61     -21.593   8.884  69.770  1.00 25.13           C
ATOM    974  CD  ARG A  61     -21.610   7.433  69.314  1.00 23.44           C
ATOM    975  NE  ARG A  61     -21.047   7.452  67.937  1.00 12.13           N"""

offset = 308
for line in data.split('\n'):
    line = line[:22] + "  {:<5d}  ".format(int(line[22:31]) + offset) + line[31:]
    print line

我还没有完成对空白的精确计数,这只是一个粗略的估计。 如果你想要更多的灵活性,而不仅仅是将数字22和31分散在你的代码中,你需要一种方法来确定你的开始和结束索引(但这与我假设数据是固定列格式的假设形成对比)。

答案 1 :(得分:1)

您最好不要尝试自行解析PDB个文件。

使用PDB-Parser。在不同的生物/计算化学包装内有许多免费提供,例如

biopython

假设您输入的是raw.pdb

,以下是使用biopython的方法
from Bio.PDB import PDBParser, PDBIO
parser=PDBParser()
structure = parser.get_structure('some_id', 'raw.pdb')
for r in structure.get_residues():
    r.id = (r.id[0], r.id[1] + 308, r.id[2])
io = PDBIO()
io.set_structure(structure)
io.save('shifted.pdb')

我google了一下,找到了一个快速的解决方案来解决你的具体问题(没有第三方依赖):

http://code.google.com/p/pdb-tools/

许多其他有用的pdb-python-script-tools - 这个脚本pdb_offset.py

这是一个独立的脚本,我只是复制了它的pdb_offset方法以显示它正常工作,您的三行示例代码位于raw.pdb

def pdbOffset(pdb_file, offset):
    """
    Adds an offset to the residue column of a pdb file without touching anything
    else.
    """

    # Read in the pdb file
    f = open(pdb_file,'r')
    pdb = f.readlines()
    f.close()

    out = []
    for line in pdb:
        # For and ATOM record, update residue number
        if line[0:6] == "ATOM  " or line[0:6] == "TER   ":
            num = offset + int(line[22:26])
            out.append("%s%4i%s" % (line[0:22],num,line[26:]))
        else:
            out.append(line) 

    return "".join(out)


print pdbOffset('raw.pdb', 308)

打印

ATOM    973  CG  ARG A 369     -21.593   8.884  69.770  1.00 25.13           C
ATOM    974  CD  ARG A 369     -21.610   7.433  69.314  1.00 23.44           C
ATOM    975  NE  ARG A 369     -21.047   7.452  67.937  1.00 12.13           N