我在主文件夹中有九个子文件夹。每个子文件夹都包含一个.pdb文件,该文件有10列。我想为每个子文件夹获取一个新的.log文件。每个新的.log文件都必须位于自己的文件夹中。我试图在每个子文件夹中创建一个不同的命名.log文件(如1.log,2.log,3.log ...)。但是我在每个文件夹中都有两个.log文件。如何在每个子文件夹中获得不同的命名.log文件?
.pdb文件:
ATOM 1 O LIG A 1 -4.657 -0.947 -1.014 1.00 0.00 O
ATOM 2 N LIG A 1 -0.173 0.679 0.052 1.00 0.00 N1+
ATOM 3 N LIG A 1 3.135 -0.678 -0.977 1.00 0.00 N
ATOM 4 N LIG A 1 3.331 0.341 1.198 1.00 0.00 N
ATOM 5 N LIG A 1 1.046 -0.695 -2.103 1.00 0.00 N
ATOM 6 C LIG A 1 -1.086 -0.167 0.546 1.00 0.00 C
ATOM 7 C LIG A 1 -2.430 0.177 0.537 1.00 0.00 C
ATOM 8 C LIG A 1 -3.476 -0.737 1.080 1.00 0.00 C
ATOM 9 C LIG A 1 1.209 0.327 0.061 1.00 0.00 C
ATOM 10 C LIG A 1 -2.803 1.409 0.008 1.00 0.00 C
.log文件:
O -4.657 -0.947 -1.014
N -0.173 0.679 0.052
N 3.135 -0.678 -0.977
N 3.331 0.341 1.198
N 1.046 -0.695 -2.103
C -1.086 -0.167 0.546
C -2.430 0.177 0.537
C -3.476 -0.737 1.080
C 1.209 0.327 0.061
C -2.803 1.409 0.008
我的代码:
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
my $search_text = qr/ATOM/;
my @fullpath= <*/*.pdb>;
foreach my $file (@fullpath) {
print $file . "\n";
my $dir = dirname($file);
for (my $i=1; $i < 10; $i++) {
open(DATA, $file);
open(out_file, ">", "$dir/$i.log") or die "Failed to open $dir/$i.log: $!";
}
while (my $line = <DATA>) {
my @fields = split /\s+/, $line;
if ($line =~ m/$search_text/) {
print out_file join("\t", @fields[2,6,7,8]), "\n";
}
}
}
close(out_file);
答案 0 :(得分:1)
主要问题是你有一个内部foreach
循环打开输入文件九次($i
是1 .. 9因为< 10
标准)和九个不同的输出文件,这发生在找到的每个 .pdb
文件中。
您需要一个文件范围的计数器,以确保以不同的方式命名每个日志文件。
您可能还会发现考虑这些要点很有用
最好尽可能限制外部模块的导入列表。默认情况下,File::Basename
导出fileparse
,fileparse_set_fstype
,basename
和dirname
。你只想要其中一个,所以你应该写
use File::Basename qw/ dirname /
我已经提到过这个循环
for (my $i=1; $i < 10; $i++) { ... }
但另外你应该记住,大多数有成就的Perl程序员使用for
代替foreach
来减少噪音(除了拼写之外,它们在各方面都是相同的)。如果您想要的只是一系列数字,那么您应该使用范围运算符,就像这样
for my $i (1 .. 9) { ... }
C风格的循环非常罕见。
您不应该使用DATA
文件句柄,因为它具有内置目的。实际上你应该在任何地方使用词法文件句柄,比如这个
open my $out_file, '>', "$dir/$i.log"
但是选择open
如果您的处理简单明了,那么最好让<>
运算符执行将每行放入$_
的默认行为。这使chomp
,split
,print
,正则表达式匹配,以及其他更简洁,因此更具可读性。
我相信这个程序可以满足您的需求。
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename qw/ dirname /;
my $search_text = qr/ATOM/;
my $infile_number;
while (my $infile = glob '*/*.pdb') {
++$infile_number;
my $dir = dirname($infile);
my $outfile = "$dir/$infile_number.log";
print "$infile => $outfile\n";
open my $in_fh, '<', $infile or die qq{Failed to open "$infile" for writing: $!};
open my $out_fh, '>', $outfile or die qq{Failed to open "$outfile" for writing: $!};
while (<$in_fh>) {
next unless /$search_text/;
my @fields = split;
print $out_fh join("\t", @fields[2,6,7,8]), "\n";
}
}
<强>更新强>
&#34;日志文件中的列不像.pdb文件中的列那样排序。 .log文件中十进制数的点/点不像.pdb文件那样在顶部和底部。当减号和加十进制数位于顶部和底部时会出现此问题。&#34;
我认为您的意思是小数点在同一列中没有对齐。我的原始程序的这个变体将解决这个问题。但是你确定要在列之间使用制表符吗?通常使用选项卡,以便计算机可以正确地分隔列,并且在用于阅读的文档中没有太多用途。
use strict;
use warnings;
use File::Basename qw/ dirname /;
use Scalar::Util qw/ looks_like_number /;
my $search_text = qr/ATOM/;
my $infile_number;
while (my $infile = glob '*/*.pdb') {
++$infile_number;
my $dir = dirname($infile);
my $outfile = "$dir/$infile_number.log";
print "$infile => $outfile\n";
open my $in_fh, '<', $infile or die qq{Failed to open "$infile" for writing: $!};
open my $out_fh, '>', $outfile or die qq{Failed to open "$outfile" for writing: $!};
while (<$in_fh>) {
next unless /$search_text/;
my @fields = split;
for (@fields) {
$_ = sprintf '%6.3f', $_ if looks_like_number($_);
}
print $out_fh join("\t", @fields[2,6,7,8]), "\n";
}
}
<强>输出强>
O -4.657 -0.947 -1.014
N -0.173 0.679 0.052
N 3.135 -0.678 -0.977
N 3.331 0.341 1.198
N 1.046 -0.695 -2.103
C -1.086 -0.167 0.546
C -2.430 0.177 0.537
C -3.476 -0.737 1.080
C 1.209 0.327 0.061
C -2.803 1.409 0.008