如何使列在perl中保持对齐

时间:2016-02-05 12:54:04

标签: regex perl

我有一个文件,我需要按顺序排序其中一个列。我已经订购了相同但面对对齐问题的几行。我没有得到如何保持列对齐。

以下是我的参考文件,我只专注于第6列:

ATOM      1  CA  GLY P  12       9.393  37.464  31.388  0.00  0.00      P1    
ATOM      2  CA  SER P  13      12.158  39.603  32.954  0.00  0.00      P1
ATOM      3  CA  VAL P  52      41.104  47.186  31.473  0.00  0.00      P1    
ATOM      4  CA  GLN P 164      36.217  27.890  29.620  0.00  0.00      P1    
ATOM      5  CA  GLN P 165      34.809  29.586  32.649  0.00  0.00      P1    
ATOM      6  CA  GLY P  12      10.007  25.374  54.523  0.00  0.00      P2    
ATOM      7  CA  SER P  13      13.212  23.440  53.698  0.00  0.00      P2    
ATOM      8  CA  ASP P  14      16.884  24.084  54.463  0.00  0.00      P2   

以下是我的代码:

#!/usr/bin/perl
use warnings;
use strict;

open (DATA, "<try.pdb") or die "not";
open (FILE,">file.txt") or die "no";
my $n=11;
foreach my $line1 (<DATA>){

if ($line1 =~ m/^ATOM\s+\d+\s+[A-Z]+\s+[A-Z]+\s+P\s+(\d+)/){

$line1 =~ s/$1/$n/g;
print FILE $line1;
}
$n++;
}

以下是我的输出,其中第4行和第5行的对齐方式发生了变化,因为在参考文件中有三位数字。

ATOM      1  CA  GLY P  12       9.393  37.464  31.388  0.00  0.00      P1    
ATOM      2  CA  SER P  13      12.158  39.603  32.954  0.00  0.00      P1   
ATOM     41  CA  VAL P  14      41.104  47.186  31.473  0.00  0.00      P1    
ATOM    153  CA  GLN P 15      36.217  27.890  29.620  0.00  0.00      P1    
ATOM    154  CA  GLN P 16      34.809  29.586  32.649  0.00  0.00      P1    
ATOM    155  CA  GLY P  17      10.007  25.374  54.523  0.00  0.00      P2    
ATOM    156  CA  SER P  18      18.212  23.440  53.698  0.00  0.00      P2    
ATOM    157  CA  ASP P  19      16.884  24.084  54.463  0.00  0.00      P2

2 个答案:

答案 0 :(得分:0)

有两种解决方案 - sprintf设置字段宽度以进行打印或使用\t

$line1 = join ( "\t", split ( ' ', $line1 ) ); 

将其拆分在任何空格上,并使用制表位将其再次粘在一起。哪个应该再次对齐您的列。

使用sprintf,您可以指定格式,并允许您配置,例如前导零,小数位数或只是字符串对齐。我认为这对你正在做的事情来说可能有点过分。

答案 1 :(得分:0)

您的脚本有两个问题。首先是空格对齐3位数的第6列条目

第二个在正则表达式上使用g标志,它破坏了碰巧与第6列相同的任何其他数据

下面的脚本纠正了这两个问题。通过匹配空白和第6列中的数字并用偶数量的空格替换来克服空间对齐。这将使用$ n最多4位数,并假设6列中的数字不会出现在第6列之前。如果是,那么正则表达式将改变第一个数字。

#!/usr/bin/perl
use warnings;
use strict;

open( DATA, "<try.pdb" ) or die "not";

#open (FILE,">file.txt") or die "no";
my $n = sprintf( "%4d", 98 );
foreach my $line1 (<DATA>) {

    if ( $line1 =~ m/^ATOM\s+\d+\s+[A-Z]+\s+[A-Z]+\s+P(\s+\d+)/ ) {

        $line1 =~ s/$1/ $n/;
        print $line1;
    }
    $n++;
    $n = sprintf( "%4d", $n );
}