Perl:用列表(文本文件或标量上下文)中的值替换文本字符串
我是一名perl新手,但读过Schwartz、foy和Phoenix的“Learning perl”,对该语言的理解很差。即使使用了这本书和网络,我仍然在挣扎 我的目标是能够做到以下几点:Perl:用列表(文本文件或标量上下文)中的值替换文本字符串,perl,list,foreach,substitution,Perl,List,Foreach,Substitution,我是一名perl新手,但读过Schwartz、foy和Phoenix的“Learning perl”,对该语言的理解很差。即使使用了这本书和网络,我仍然在挣扎 我的目标是能够做到以下几点: 搜索特定文件夹(当前文件夹)并获取具有完整路径的文件名。使用完整路径和当前文件夹名保存文件名 打开一个模板文件,在特定位置(例如使用替换)插入具有完整路径的文件名以及当前foldername(在同一文本文件的另一个位置,到目前为止我还没有得到) 将新修改的文件保存到特定位置(当前文件夹)的新文件中 我有许多要
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;
替换函数不会用$FastQFileName中列出的文件列表替换“@”。我将“@”替换为GLOB(0x8ab1dc)
我这样做不对吗?我是否应该不使用替换,因为这无法完成,而是在template.txt文件中插入文件列表($fastqfilenames)?我可以用文件内容(例如s/A/{r file.txt…)代替$fastqfilenames吗?有什么建议吗
干杯
杰姆斯
编辑:
这让一切变得更好
foreach (@secontrol_template) {
s/@/$fastqfilenames/g;
push @secontrol, $_;
}
正如这两个建议一样,$fastqfiles是一个文件句柄
替换为:open(my($fastqfilenames),“
$fastqfilenames
是一个文件句柄。您必须先从文件句柄中读取信息,然后才能使用它
但是,您还有其他问题
您正在将所有文件名打印到一个文件中,然后从该文件中读取它们。这不仅是一个有问题的设计(为什么要再次从该文件中读取,因为您已经在一个数组中拥有了所需的内容?),它甚至无法工作:
由于性能原因,Perl缓冲文件I/O。您写入文件的行可能实际上还不存在,因为Perl正在等待,直到它保存了一大块数据,才能一次全部写入
您可以通过几种不同的方式覆盖这种缓冲行为(如果您已经完成了写入操作,那么关闭文件句柄是最简单的),但是正如我所说的,没有理由再次打开文件并从中读取
另外请注意,正则表达式替换中的/e
选项将替换作为Perl代码进行计算。在您的情况下,这不是必需的,因此您应该删除它
解决方案:只需使用先前在模板中替换时创建的@fastqfiles
变量,而不是重新打开并读取文件。用文件名替换@
的确切含义尚不清楚
- 是否要将每个
一起替换为所有文件名的列表?如果是这样,在替换之前,您可能需要以某种方式将所有文件名一起替换@
- 是否要为每个文件名创建一个单独版本的模板文件?如果是这样,则需要一个内部的
循环,该循环将遍历每个模板的每个文件名。此外,还需要一些其他内容,而不是简单的替换,因为替换将在第一次通过时更改原始字符串。如果使用Perl5.16,您可以使用for
选项以非破坏性方式替换:/r
否则,您应该在替换之前复制到另一个变量push(@secontrol,s/@/$file\u name/gr);
$\u=~ s/@/$fastqfilenames/eg;
$fastqfilenames
是一个文件句柄,而不是文件内容
无论如何,我建议使用模块来完成这类工作(文件文本替换)。我是新手,因此我的程序设计很差。这与我使用“我了解如何使用”有关“或者我想出来的。
@fastqfiles
中的文件名列表可以用来替换模板文件中的符号@,但我不知道如何替换它(除了Unix sed/awk中的一些基本知识,因此尝试了替换)。我不知道如何循环@fastqfiles
的内容并将其保存到我的模板文件中(存储在@secontrol\u template
)中。我想我可以理解使用@fastqfiles
数组的标量/列表来替代。也许,这是设计缺陷的一部分。[Text::template]()链接非常有用。我可能会使用它来修改我的模板文件。绝对值得研究。谢谢:)
foreach (@secontrol_template) {
s/@/$fastqfilenames/g;
push @secontrol, $_;
}
my $fastqfilenames = join "\n", @fastqfiles;