我有多个输入文件(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);
}
}
答案 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";
}
}