0

私はPerlの初心者ですが、Schwartz、foy、Phoenixによる「LearningPerl」を読んだことがあり、言語の理解が弱いです。本やウェブを使った後も、まだ苦労しています。

私の目標は、次のことができるようにすることです。

  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)に置き換えます。

私はこれを間違った方法でやっていますか?代用を使用することはできません。代わりに、ファイルのリスト($ fastqfilenames)をtemplate.txtファイルに挿入する必要がありますか?$ fastqfilenamesの代わりに、ファイルのコンテンツ(s / A / {r file.txt ...など)に置き換えることはできますか?助言がありますか?

乾杯、

JamesT

編集:

これはそれをすべて良くしました。

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

そして両方の提案として、$fastqfilesはファイルハンドルです。

これを置き換えました: open(my($ fastqfilenames)、 "<"、 "fastqfilenames.txt")またはdie "Ca n'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 に答える