Bash 根据模式将文件拆分为两行

Bash 根据模式将文件拆分为两行,bash,sed,split,awk,lines,Bash,Sed,Split,Awk,Lines,我有以下格式的文件: 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

我有以下格式的文件:

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_u$column,其中$basename是输入文件的基本名称,$column是位置22-23处的字符(在本例中为A或B)。我不知道如何检查两个连续的行来确定拆分点。

这里有一个简单的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()

这里是一个简单的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()

这是一个
awk
版本

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

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

这是一个
awk
版本

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


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

在awk中,您可以使用
next
print…>文件名
,以完成任务。使用全局变量查看前一行。Python脚本是否适合您?当然。起初,我希望避免任何外部脚本。但由于解析数据时遇到大量异常,这比预期的时间要长。这是我有史以来第一次认真尝试编码,几天之内我已经写了500行了。。。我现在需要的是尽快完成工作,不管怎样。在awk中,您可以使用
next
print…>文件名
,以完成任务。使用全局变量查看前一行。Python脚本是否适合您?当然。起初,我希望避免任何外部脚本。但由于解析数据时遇到大量异常,这比预期的时间要长。这是我有史以来第一次认真尝试编码,几天之内我已经写了500行了。。。我现在需要的是尽快完成这项工作,不管怎样。它是有效的!谢谢你。唯一的问题是,当我复制了链名时,它会用新文件覆盖上一个文件。这意味着,如果我有两个名为A的链,它将写入文件A一次,然后用下一次事件覆盖它。我需要想出一个办法来防止这种情况发生。也许bes的方法是添加一个计数器,这样我就可以编写文件A1、文件B2、文件C3、文件A4等等…@mirix:好的,新版本应该可以这样做。我没有测试它,它是有效的!谢谢你。唯一的问题是,当我复制了链名时,它会用新文件覆盖上一个文件。这意味着,如果我有两个名为A的链,它将写入文件A一次,然后用下一次事件覆盖它。我需要想出一个办法来防止这种情况发生。也许bes的方法是添加一个计数器,这样我就可以编写文件A1、文件B2、文件C3、文件A4等等…@mirix:好的,新版本应该可以这样做。我没有测试它。我将不得不花更多的时间使用awk,它肯定比我的解决方案要短得多。@Tom:到目前为止,您的python脚本已经证明是100%可靠的,而这个awk脚本在比示例中提供的更复杂的情况下会犯一些错误。@mirix,这一切都在编程方面。在任何情况下,我的awk解决方案都可以进行微调,以与Python的解决方案相匹配。。。。因为它只是文件/文本解析..@ghostdog74;是的,事实上,awk one liner不工作的原因如下(如其他线程中所述):有时,第二列中的值较大,第一列和第二列之间没有空间,因此从awn的角度来看,这只是一列,因此第五列成为第四列。在PDB格式中,每个字段都占据固定位置,因此最好提供特定位置,而不是使用分隔符。是否可以在awk中指定范围?我的意思是$22-$25(带-F“”)?我必须花更多的时间在awk上,它肯定比我的解决方案短得多。@Tom:到目前为止,您的python脚本已经证明是100%可靠的,而这个awk脚本在比示例中提供的更复杂的情况下会犯一些错误。@mirix,这一切都在编程方面。在任何情况下,我的awk解决方案都可以进行微调,以与Python的解决方案相匹配。。。。因为它只是文件/文本解析..@ghostdog74;是的,事实上,awk one liner不工作的原因如下(如其他线程中所述):有时,第二列中的值较大,第一列和第二列之间没有空间,因此从awn的角度来看,这只是一列,因此第五列成为第四列。在PDB格式中,每个字段都占据固定位置,因此最好提供特定位置,而不是使用分隔符。是否可以在awk中指定范围?我的意思是22-25美元(带-F“)?