0

我是 perl 新手,但读过 Schwartz、foy 和 Phoenix 的“Learning Perl”,对语言的理解很薄弱。即使在使用了这本书和网络之后,我仍然在苦苦挣扎。

我的目标是能够做到以下几点:

  1. 搜索特定文件夹(当前文件夹)并获取具有完整路径的文件名。使用完整路径和当前文件夹名保存文件名。

  2. 打开一个模板文件并在特定位置(例如使用替换)以及当前文件夹名(在同一文本文件的另一个位置,我还没有做到这一点)插入具有完整路径的文件名。

  3. 将新修改的文​​件保存到特定位置(当前文件夹)的新文件中。

我有许多要处理的文件/文件夹,并计划将 perl 程序复制到每个文件夹中,以便 perl 程序可以创建新的 .

我到目前为止......:

use strict;
use warnings;
use Cwd;
use File::Spec;
use File::Basename;
my $current_dir = getcwd;
open SECONTROL_TEMPLATE, '<secontrol_template.txt' or die "Can't open SECONTROL_TEMPLATE: $!\n";
my @secontrol_template = <SECONTROL_TEMPLATE>;
close SECONTROL_TEMPLATE;
opendir(DIR, $current_dir) or die $!;
my @seq_files = grep {
    /gz/
    } readdir (DIR);
open FASTQFILENAMES, '> fastqfilenames.txt' or die "Can't open fastqfilenames.txt: $!\n";
my @fastqfiles;
foreach (@seq_files) {
    $_ = File::Spec->catfile($current_dir, $_);
    push(@fastqfiles,$_);
}
print FASTQFILENAMES @fastqfiles;
open (my ($fastqfilenames),  "<", "fastqfilenames.txt") or die "Can't open fastqfilenames.txt: $!\n";
my @secontrol;
foreach (@secontrol_template) {
    $_ =~ s/@/$fastqfilenames/eg;
    push(@secontrol,$_);
}
open SECONTROL, '> secontrol.txt' or die "Can't open SECONTROL: $!\n";
print SECONTROL @secontrol;
close SECONTROL;
close FASTQFILENAMES;

我的问题是我无法弄清楚如何使用我的文件列表来替换模板文本文件中的“@”:

my @secontrol;
foreach (@secontrol_template) {
    $_ =~ s/@/$fastqfilenames/eg;
    push(@secontrol,$_);
}

替换函数不会将“@”替换为 $fastqfilenames 中列出的文件列表。我将“@”替换为 GLOB(0x8ab1dc)。

我这样做是错误的吗?我是否应该不使用替代品,因为这无法做到,然后在 template.txt 文件中插入文件列表($fastqfilenames)?我可以用文件内容代替 $fastqfilenames(例如 s/A/{r file.txt ...)吗?有什么建议么?

干杯,

詹姆斯T

编辑:

这让一切变得更好。

foreach (@secontrol_template) {
    s/@/$fastqfilenames/g;
    push @secontrol, $_;
}

正如这两个建议, $fastqfiles 是一个文件句柄。

替换这个: open (my ($fastqfilenames), "<", "fastqfilenames.txt") or die "Can't open fastqfilenames.txt: $!\n";

有了这个:

my $fastqfilenames = join "\n", @fastqfiles; 

一切都很好。谢谢你们俩。

4

2 回答 2

0

$fastqfilenames是一个文件句柄。您必须先从文件句柄中读取信息,然后才能使用它。

但是,您还有其他问题。

您正在将所有文件名打印到文件中,然后从文件中读取它们。这不仅是一个有问题的设计(为什么要再次从文件中读取,因为您已经在数组中拥有了所需的内容?),它甚至也不起作用:

Perl 出于性能原因缓冲文件 I/O。您写入文件的行实际上可能还不存在,因为 Perl 一直在等待,直到它保存了一大块数据,才一次将其全部写入。

您可以通过几种不同的方式覆盖此缓冲行为(如果您完成写入文件句柄,则关闭文件句柄是最简单的),但正如我所说,没有理由再次重新打开文件并从中读取。

另请注意,/e正则表达式替换中的选项将替换评估为 Perl 代码。在您的情况下,这不是必需的,因此您应该将其删除。

解决方案:不要重新打开文件并读取它,只需使用@fastqfiles您之前在模板中替换时创建的变量即可。目前尚不清楚用文件名替换的确切含义@

  • 你想@用所有文件名的列表一起替换每个吗?如果是这样,您可能需要在进行替换之前以某种方式join将文件名放在一起。

  • 您想为每个文件名创建一个单独版本的模板文件吗?如果是这样,您需要一个内部for循环来遍历每个模板的每个文件名。而且您需要的不仅仅是简单的替换,因为替换会在第一次通过时更改原始字符串。如果您使用的是 Perl 5.16,则可以使用/r非破坏性替换选项: push(@secontrol,s/@/$file_name/gr);否则,您应该在替换之前复制到另一个变量。

于 2013-03-25T10:13:27.190 回答
0

$_ =~ s/@/$fastqfilenames/eg;

$fastqfilenames是文件句柄,而不是文件内容。

无论如何,我建议使用Text::Template模块来完成这种工作(文件文本替换)。

于 2013-03-25T10:19:28.543 回答