Print output in predefined format Perl

一个人想着一个人 提交于 2019-12-19 09:30:30

问题


I'm generating 3D coordinates (x,y,z) to a file with the following code.

for (my $x = 0.000; $x < 4.200; $x += 1.400) {
    for (my $y = 0.000; $y < 4.200; $y += 1.400) {
        for (my $z = 0.000; $z < 4.200; $z += 1.400) {
            push @arr_grid, "$x  $y  $z\n";
        }
    }
}  
foreach (@arr_grid) {
    say "HETATM 1 O  HOH  1  $_   O";
}

Now, my problem is that I want to get the output with a precise format (PDB) with Index values like,

1-6    7-11 13-16 18-20 23-26    31-38   39-46    47-54                      77-78  
(Name) (S.No)                     (x)     (y)      (z)
HETATM    1  O    HOH     1      -8.863  16.944  14.289                       N  
HETATM  100  O    HOH    16     -15.352  11.525   5.325                       N  
HETATM  117  O    HOH    16     -12.954   9.717   5.182                       C  
HETATM  126  O    HOH    17     -19.225  11.667  -0.391                       C  
HETATM 1005  O    HOH    97       9.246  23.287  11.503                       O  

Here the x,y,z coordinates shoulb be of data type real(8.2) and others are right justified. x,y,z values are not those generated from program. I placed arbitrary values. Please help me.


回答1:


You want to use perl's format options for presenting output data in predefined ways.

You can read about it here.

Your example, rewritten a bit:

for ($x = 0.000; $x < 4.200; $x += 1.400) {
    for ($y = 0.000; $y < 4.200; $y += 1.400) {
        for ($z = 0.000; $z < 4.200; $z += 1.400) {
        write;
        }
    }
}

format STDOUT_TOP =
1-6    7-11 13-16 18-20 23-26    31-38   39-46    47-54                      77-78
(Name) (S.No)                     (x)     (y)      (z)
.

format STDOUT =
HETATM    1  O    HOH     1      @<<<<<< @<<<<<<  @<<<<<<                     N
                                 $x      $y       $z
.

The FORMAT_TOP is printed every $= (or $FORMAT_LINES_PER_PAGE) so reset this variable if you want it printed more rarely or a ridiculously high number if you want it printed only once.

Output example:

1-6    7-11 13-16 18-20 23-26    31-38   39-46    47-54                      77-78
(Name) (S.No)                     (x)     (y)      (z)
HETATM    1  O    HOH     1      0       0        0                           N
HETATM    1  O    HOH     1      0       0        1.4                         N
HETATM    1  O    HOH     1      0       0        2.8                         N
HETATM    1  O    HOH     1      0       0        4.2                         N
HETATM    1  O    HOH     1      0       1.4      0                           N
HETATM    1  O    HOH     1      0       1.4      1.4                         N
HETATM    1  O    HOH     1      0       1.4      2.8                         N
HETATM    1  O    HOH     1      0       1.4      4.2                         N

I have got one more problem: when I'm printing numbers with decimal points like

HETATM    1  O    HOH     1      -10     -3.4    -8                          N
HETATM    1  O    HOH     1      -10     -3.4    -6.6                        N
HETATM    1  O    HOH     1      -10     -3.4    -5.2                        N
HETATM    1  O    HOH     1      -10     -3.4    -3.8                        N
HETATM    1  O    HOH     1      -10     -3.4    -2.4                        N
HETATM    1  O    HOH     1      -10     -3.4    -1                          N
HETATM    1  O    HOH     1      -10     -3.4    0.4                         N
HETATM    1  O    HOH     1      -10     -3.4    1.8                         N
HETATM    1  O    HOH     1      -10     -3.4    3.2                         N
HETATM    1  O    HOH     1      -10     -3.4    4.6                         N
HETATM    1  O    HOH     1      0     -3.4    6                           N

In the above columns, I need to print the dot of decimal in the same index. When I'm doing calculations and updating values, the dots in decimals are shifting. i need output like

HETATM    1  O    HOH     1      -10     -3.4    -8.0                        N
HETATM    1  O    HOH     1      -10     -3.4    -6.6                        N
HETATM    1  O    HOH     1      -10     -3.4    -5.2                        N
HETATM    1  O    HOH     1      -10     -3.4    -3.8                        N
HETATM    1  O    HOH     1      -10     -3.4    -2.4                        N
HETATM    1  O    HOH     1      -10     -3.4    -1.0                        N
HETATM    1  O    HOH     1      -10     -3.4     0.4                        N
HETATM    1  O    HOH     1      -10     -3.4     1.8                        N
HETATM    1  O    HOH     1      -10     -3.4     3.2                        N
HETATM    1  O    HOH     1      -10     -3.4     4.6                        N
HETATM    1  O    HOH     1      -10     -3.4     6.0                        N

Edit 1:
Example to a dumpfile:

open(DUMPFILE,">output.txt");

for ($x = 0.000; $x < 4.200; $x += 1.400) {
    for ($y = 0.000; $y < 4.200; $y += 1.400) {
        for ($z = 0.000; $z < 4.200; $z += 1.400) {
        write DUMPFILE;
        }
    }
}

close(DUMPFILE);


format DUMPFILE_TOP =
1-6    7-11 13-16 18-20 23-26    31-38   39-46    47-54                      77-78
(Name) (S.No)                     (x)     (y)      (z)
.

format DUMPFILE =
HETATM    1  O    HOH     1      @<<<<<< @<<<<<<  @<<<<<<                     N
                                 $x      $y       $z
.



回答2:


Presumably, you could replace the existing:

        push @arr_grid, "$x  $y  $z\n";

with some suitable variation of:

        push @arr_grid, sprintf("%8.2f  %8.2f  %8.2f\n", $x, $y, $z);

This gives you control over the format of the numbers.




回答3:


You can use printf to specify spacing, alignment, and significant digits. Something like this might work:

my @arr_grid;
for (my $x = 0.000; $x < 4.200; $x += 1.400) {
    for (my $y = 0.000; $y < 4.200; $y += 1.400) {
        for (my $z = 0.000; $z < 4.200; $z += 1.400) {
            push @arr_grid, [$x, $y, $z];
        }
    }
} 
foreach (@arr_grid) {
    printf "HETATM%5d %2s%2s HOH     1    %8.3f%8.3f%8.3f\n", 1, 'O', '', @$_;
}

It might might make more sense though to use a perl module designed for the PDB format such as Chemistry::File::PDB or Bio::Structure::IO::pdb



来源:https://stackoverflow.com/questions/8775050/print-output-in-predefined-format-perl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!