perl从文件中删除行

时间:2011-10-19 13:10:43

标签: perl bash

我的文件看起来像:

ATOM 2517 O   VAL 160 8.337  12.679  -2.487
ATOM 2518 OXT VAL 160 7.646  12.461  -0.386
TER 
ATOM 2519 N   VAL 161 -14.431  5.789 -25.371
ATOM 2520 H1  VAL 161 -15.336  5.698 -25.811
ATOM 2521 H2  VAL 161 -13.416 10.529  17.708
ATOM 2522 H3  VAL 161 -14.363  9.436  18.498
ATOM 2523 CA  VAL 161   4.400  9.233  16.454
ATOM 2524 HA  VAL 161   3.390  9.170  16.047

我必须删除“TER”,“TER”之前的行和TER之后的行后的3行,并使文件连续如下:

ATOM 2517 O   VAL 160   8.337 12.679  -2.487
ATOM 2519 N   VAL 161 -14.431  5.789 -25.371
ATOM 2523 CA  VAL 161   4.400  9.233  16.454
ATOM 2524 HA  VAL 161   3.390  9.170  16.047

4 个答案:

答案 0 :(得分:3)

一个简单的逐行脚本。

用法: perl script.pl -i.bak fileglob

E.g。 perl script.pl -i.bak File*MINvac.pdb

这将更改原始文件,并使用扩展名.bak保存每个文件的备份。请注意,如果TER行显得太靠近文件末尾,则会引发警告。另一方面,其他解决方案也将如此。

如果您不想保存备份(请谨慎使用,因为更改是不可逆转的!),请改用-i

<强>代码:

#!/usr/bin/perl
use v5.10;
use strict;
use warnings;

my $prev;
while (<>) {
    if (/^TER/) {
        print scalar <>;  # print next line
        <> for 1 .. 3;    # skip 3 lines
        $prev = undef;    # remove previous line
    } else {
        print $prev if defined $prev;
        $prev = $_;
    }
    if (eof) {  # New file next iteration?
        print $prev;
        $prev = undef;
    }
}

答案 1 :(得分:0)

那么,对于每组6个连续行,你想要丢弃除第三行之外的所有行如果第二行是TER

TIMTOWTDI,但这应该有效:

my @queue;
while (<>) {
    push @queue, $_;
    @queue = $queue[2]  if @queue == 6 and $queue[1] =~ /^TER$/;
    print shift @queue  if @queue == 6;
}
print @queue;  # assume no TERs in last 4 lines

答案 2 :(得分:0)

我意识到我应该用Perl编写它,但现在我已经用Python编写了它。无论如何我都会张贴它,因为它可能被证明是有用的,不会有任何伤害。

#!/usr/bin/python2.7
import sys
import glob
import os

try:
    dir = sys.argv[1]
except IndexError:
    print "Usage: "+sys.argv[0]+" dir"
    print "Example: "+sys.argv[0]+" /home/user/dir/"
    sys.exit(1)

for file in glob.glob(os.path.join(dir, 'File*_*MINvac.pdb')):
    fin = open(file, "r")
    content = fin.readlines()
    fin.close()

    for i in range(0, len(content)):
        try:
            if "TER" in content[i]:
                del content[i]
                del content[i-1]
                del content[i:i+3]
        except IndexError:
            break
    fout = open(file, "w")
    fout.writelines(content)
    fout.close()

编辑:添加了对多个文件的支持,例如OP想要的。

答案 3 :(得分:-1)

use strict;
use warnings;
use Tie::File;

my @array;

tie @array, 'Tie::File', 'myFile.txt' or die "Unable to tie file";

my %unwanted = map  { $_ => 1 }                # Hashify ...
               map  { $_-1, $_, $_+2 .. $_+4 } # ... the five lines ...
               grep { $array[$_] =~ /^TER/ }   # ... around 'TER'  ...
               0 .. $#array ;                  # ... in the file

# Remove the unwanted lines
@array = map { $array[$_] } grep { ! $unwanted{$_} } 0 .. $#array;

untie @array;  # The end