2013-03-25 12 views
0

我是一個perl新手,但已閱讀Schwartz,foy和Phoenix的「Learning Perl」,並且對語言理解力差。即使在使用本書和網絡之後,我仍然在掙扎。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)替換了「@」。

我這樣做是錯誤的嗎?我不應該使用替代品,因爲這不能完成,而是將文件列表($ fastqfilenames)插入到template.txt文件中?我可以使用文件內容(例如s/A/{r file.txt ...)來替代$ fastqfilenames。有什麼建議麼?

乾杯,

JamesT

編輯:

這使得它要好。

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

作爲這兩個建議,$ fastqfiles是一個文件句柄。

替換爲: open(my($ fastqfilenames),「<」,「fastqfilenames.txt」)或死「無法打開fastqfilenames.txt:$!\ n」;

與此:

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

使這一切良好。謝謝你們。

回答

0

$fastqfilenames是一個文件句柄。在使用之前,必須從文件句柄中讀取信息。

但是,您還有其他問題。

您正在將所有文件名打印到文件中,然後將它們從文件中讀出。這不僅是一個值得懷疑的設計(爲什麼再次讀取文件,因爲您已經擁有了數組中的所需內容?),它也不會工作:

由於性能原因,Perl緩衝文件I/O。您寫入文件的行可能實際上還沒有,因爲Perl正在等待,直到它有大量的數據保存起來,才能立刻寫入。

你可以用幾種不同的方式覆蓋這個緩衝行爲(如果你已經寫完了,關閉文件句柄是最簡單的),但正如我所說的,沒有理由再重新打開文件並從中讀取無論如何。

另請注意,正則表達式替換中的/e選項會將替換評估爲Perl代碼。這不是必要的,所以你應該刪除它。

解決方案:而不是重新打開文件並讀取它,只需使用之前在模板中替換時創建的@fastqfiles變量。用文件名代替@並不清楚你的意思。

  • 是否要將每個@替換爲所有文件名的列表?如果是這樣,您可能需要以某種方式將join the filenames放在一起,然後再進行更換。

  • 是否要爲每個文件名創建單獨版本的模板文件?如果是這樣,你需要一個內部的for循環遍歷每個模板的每個文件名。而且你需要的不是一個簡單的替換,因爲替換會在第一次改變原來的字符串。如果您使用的是Perl 5.16,則可以使用/r選項進行非破壞性替換:push(@secontrol,s/@/$file_name/gr);否則,應在複製之前複製另一個變量。

+0

我是新手,因此我的程序設計很差。這與我使用「我瞭解如何使用」或我所知道的有關。 '@ fastqfiles'中的文件名列表可以用來替換模板文件中的符號@,但我不知道如何去除(除了Unix sed/awk中的一些基本知識,因此是替代嘗試)。我不知道如何循環並將'@ fastqfiles'的內容保存到我的模板文件(存儲在@ secontrol_template'中)。我想我可以理解在替換中使用'@ fastqfiles'數組的標量/列表。也許,這是設計缺陷的一部分。 – JamesT 2013-03-25 13:06:25

0

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

$fastqfilenames是一個文件句柄,而不是文件內容。

無論如何,我建議使用Text::Template模塊來完成這種工作(文件文本替換)。

+0

[Text :: Template](http://search.cpan.org/perldoc?Text%3a%3aTemplate)鏈接非常有用。我可能會用它來修改我的模板文件。絕對有東西要看。謝謝 :) – JamesT 2013-03-25 13:10:53