[英]How can I create a new output file for each subfolder under a main folder using perl?
我的主文件夾中有100個子文件夾。 他們有不同的名字。 每個子文件夾都包含一個.txt文件,該文件有10列。 我想為每個子文件夾獲取一個新的.txt文件。 每個新的.txt文件必須位於其自己的文件夾中。 也就是說,每個子文件夾中將有2個.txt文件(舊的和新的)。 我試圖從每個.txt文件中選擇以“ ATOM”開頭的行以及一些2,6,7和8列。 我的代碼如下。 它不能正常工作。 它不會創建新的.txt文件。 我該如何解決這個問題?
#!/usr/bin/perl
$search_text = "ATOM";
@files = <*/*.txt>;
foreach $file (@files) {
print $file . "\n";
open(DATA, $file);
open(OUT_FILE, ">$file a.txt");
while ($line = <DATA>)
{
@fields = split /\s+/, $line;
if ($line =~ m/$search_text/)
{
print OUT_FILE "$fields[2]\t$fields[6]\t$fields[7]\t$fields[8]\n";
}
}
}
close(OUT_FILE);
要將輸出文件a.txt
與輸入文件放在同一目錄中,您需要從輸入文件名中提取目錄名,並將其添加到輸出文件名( a.txt
)之前。 有兩種方法可以做到這一點; 可能最簡單的方法是使用標准模塊File :: Basename中的 dirname()
:
use File::Basename;
my $dir = dirname($file);
open(OUT_FILE, ">", "$dir/a.txt") or die "Failed to open $dir/a.txt: $!";
或者您可以直接使用File :: Spec :
use File::Spec;
my ($volume, $dir) = File::Spec->splitpath($file);
my $outname = File::Spec->catpath($volume, $dir, 'a.txt');
open(OUT_FILE, ">", $outname) or die "Failed to open $outname: $!";
或者您可以使用regexp替換 :
my $outname = ( $file =~ s![^/]+$!a.txt!r );
open(OUT_FILE, ">", $outname) or die "Failed to open $outname: $!";
PS。 無論如何,我建議您采取一些良好的習慣,以幫助您編寫更好的Perl腳本:
始終use strict;
啟動腳本use strict;
並use warnings;
。 修復它們產生的任何錯誤和警告。 特別是,請使用my
聲明所有局部變量,以使其在詞法范圍內。
檢查open()
類的函數的返回值,並在失敗時中止腳本。 (我在上面的示例中已經做到了。)
使用open()
的三參數形式,就像我在上面的示例中所做的一樣。 如果文件名包含有趣的字符,則中斷的可能性要小得多。
考慮使用詞法范圍的文件句柄( open my $out_file, ...
),而不是全局文件句柄( open OUT_FILE, ...
)。 在上面的代碼段中,我沒有這樣做,因為我想讓它們與您的其余代碼兼容,但這是一個好習慣。
如果您要預先聲明一個正則表達式(例如$search_text
,請使用qr//
而不是純字符串,如下所示:
my $search_text = qr/ATOM/;
它效率更高一些,特殊字符的引用規則也更精明。
要從數組中打印多列,請考慮使用join()
和列表切片,如下所示:
print OUT_FILE join("\\t", @fields[2,6,7,8]), "\\n";
最后,如果我是您,我將重新考慮文件命名方案:輸出文件名a.txt
與輸入文件名glob *.txt
匹配,因此如果您連續運行兩次腳本,腳本可能會損壞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.