Perl - 在具有特定扩展名的所有文件中打印标题

时间:2016-02-21 18:17:47

标签: perl

我有多个输入文件(outputXXX.pdb),我想为其编写输出文件(outputXXX.gjf)。

输入文件具有以下格式:

ATOM      1  CAY GLY X   1      -0.124   0.401  -0.153  1.00  2.67      PEP
ATOM      2  HY1 GLY X   1      -0.648   0.043  -1.064  1.00  0.00      PEP
ATOM      3  HY2 GLY X   1      -0.208   1.509  -0.145  1.00  0.00      PEP

对于每个输入文件,我想创建一个输出文件,其中包含在单独的文本文件'gaussian.txt'中找到的标题,以及获取每个相应输入的第2,6,7,8列中的内容文件,产生这样的东西:

Title
Header Line 1
Header Line 2

CAY   -0.124   0.401  -0.153
HY1   -0.648   0.043  -1.064  
HY2   -0.208   1.509  -0.145

以下是我当前的脚本。

#!/usr/bin/perl

use strict;
use warnings;

use File::Basename;

my $input_path  = $ARGV[0];
my $output_path = $ARGV[1];

foreach my $filename (<$input_path/*.pdb>) {

    my $output_file = basename( $filename, '.pdb' );

    open( my $input_fh,  "<", $filename )                       or die $!;
    open( my $output_fh, ">", "$output_path/$output_file.gjf" ) or die $!;
    open( my $header,    "<", "gaussian.txt" )                  or die $!;

    while (<$input_fh>) {
        if ( /CAY/ .. /HT2/ ) {
            print {$output_fh} $header;
            print {$output_fh} join( " ", +(split)[ 2, 6, 7, 8 ] ), "\n";
        }
    }

    close($output_fh);
    close($input_fh);
}

它写了outputXXX.gjf文件然而不打印标题并且不保留格式,更不用说它打印GLOB ??

GLOB(0x1622950)CAY -0.124 0.401 -0.153
GLOB(0x1622950)HY1 -0.648 0.043 -1.064
GLOB(0x1622950)HY2 -0.208 1.509 -0.145

非常感谢有关如何改进我的脚本的任何建议。

更新以下更新的代码。这很麻烦(我不是很有经验),但能够实现以下输出。

输出:

 Title
 Header Line 1
 Header Line 2

 CAY-0.124 0.401 -0.153
 HY1-0.648 0.043 -1.064
 HY20.208 1.509 -0.145

代码:

#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;

my $input_path = $ARGV[0];
my $output_path = $ARGV[1];
my $header = "gaussian.txt";

foreach my $filename (<$input_path/*.pdb>) {
        my $output_file = basename ( $filename, '.pdb');
    open (my $header_fh, "<", $header) or die $!;
        my @lines;
        while (<$header_fh>) {
        push (@lines, $_);
    open (my $output_fh, ">", "$output_path/$output_file.gjf") or die $!;
        print {$output_fh} @lines;
    open (my $input_fh, "<", $filename) or die $!;
        while ( <$input_fh>) {
        if (/CAY/../HT2/) {
                print {$output_fh} join (" ", (split)[2,6,7,8]), "\n";
                }
                }
        close($output_fh);
        close($input_fh);
}
}

2 个答案:

答案 0 :(得分:2)

$header不包含标题字符串,但其文件句柄:

open (my $header, "<", "gaussian.txt") or die $!;

使用文件的上下文填充$ header。

另外,不要在每行之前打印标题。

答案 1 :(得分:1)

我会这样做。我所做的主要改变是

  • use autodie而非显式检查每个文件操作的成功

  • 使用do块将gaussian.txt的内容读入$header

  • .pdb文件类型替换为.gjf,而不是将其添加到最后

  • 使用select使GJF文件成为默认输出,以便print语句不需要显式文件句柄

  • 使用next unless /\S/处理包含非空格字符的输入文件的每一行

  • 使用数组切片的字符串插值在输出中放置空格以避免join调用


#!/usr/bin/perl

use strict;
use warnings;
use v5.10.1;
use autodie;

use File::Basename 'basename';

my ( $pdb_path, $gjf_path ) = @ARGV;

my $header = do {
    open my $fh, '<', 'gaussian.txt';
    local $/;
    <$fh>;
};

for my $pdb_file ( glob "$pdb_path/*.pdb" ) {

    ( my $gjf_file = basename($pdb_file) ) =~ s/\.pdb$/.gjf/;

    open my $gjf_fh, '>', "$gjf_path/$gjf_file";
    select $gjf_fh;

    print $header;

    open my $pdb_fh, '<', $pdb_file;

    while ( <$pdb_fh> ) {
        next unless /\S/;
        my @fields = split;
        print "@fields[2,6,7,8]\n";
    }
}