Perl在文件之间循环并将其内容写入输出文件时跳过某些文件

Perl在文件之间循环并将其内容写入输出文件时跳过某些文件,perl,Perl,我在Perl方面遇到了一个问题,我希望这里有人能帮我弄清楚到底发生了什么。我在一个名为RawData的目录中有大约130000个.txt文件,我有一个Perl程序将它们加载到一个数组中,然后在这个数组中循环,加载每个.txt文件。为简单起见,假设我有四个循环使用的文本文件 File1.txt File2.txt File3.txt File4.txt 每个.txt文件的内容如下所示: 007 C03XXYY ZZZZ 008 A01XXYY ZZZZ 009 A02X

我在Perl方面遇到了一个问题,我希望这里有人能帮我弄清楚到底发生了什么。我在一个名为
RawData
的目录中有大约130000个.txt文件,我有一个Perl程序将它们加载到一个数组中,然后在这个数组中循环,加载每个.txt文件。为简单起见,假设我有四个循环使用的文本文件

 File1.txt
 File2.txt
 File3.txt
 File4.txt
每个.txt文件的内容如下所示:

 007 C03XXYY    ZZZZ
 008 A01XXYY    ZZZZ
 009 A02XXYY    ZZZZ
其中
X,Y,Z
是数字。在我下面的简化代码中,程序只提取每个.txt文件中的行
007
,将
XX
保存为
ID
,忽略
YY
并获取我调用的变量数据
zzzzzz
。然后,它将所有内容写入具有以下代码中指定的头的文件:

 #!/usr/bin/perl

 use warnings;
 use strict;

 open(OUTFILE, "> ../Data/OutputFile.csv") or die $!;

 opendir(MYDIR,"../RawData")||die $!;
 my @txtfiles=grep {/\.txt$/} readdir(MYDIR);
 closedir(MYDIR);

 print OUTFILE "ID,VarName,VarVal\n";

 foreach my $txtfile (@txtfiles){

        #Prints to the screen so I can see where I am in the loop.
        print $txtfile","\n";

        open(INFILE, "< ../RawData/$txtfile") or die $!;

        while(<INFILE>){

             if(m{^007 C03(\d{2})(\d+)(\s+)(.+)}){
                print OUTFILE "$1,VarName,$4\n"
        }
             }
        }
#/usr/bin/perl
使用警告;
严格使用;
打开(OUTFILE,“>../Data/OutputFile.csv”)或die$!;
opendir(MYDIR,“../RawData”)| | die$!;
my@txtfiles=grep{/\.txt$/}readdir(MYDIR);
closedir(MYDIR);
打印输出文件“ID,VarName,VarVal\n”;
foreach my$txtfile(@txtfiles){
#打印到屏幕上,以便我可以看到我在循环中的位置。
打印$txtfile“,“\n”;
打开(填充,“<../RawData/$txtfile”)或死亡$!;
while(){
if(m{^007 C03(\d{2})(\d+(\s+))}){
打印输出文件“$1,VarName,$4\n”
}
}
}
我遇到的问题是,例如
File3.txt
的内容没有显示在
OutputFile.csv
中。但是,Perl没有找到匹配项并不是问题,因为我通过删除
OUTFILE
并查看代码打印到终端屏幕的内容来检查
if
语句是否正在执行n、 出现的正是应该出现的

此外,如果我只是通过注释掉
opendir
closedir
内容并执行类似于
my@textfile=“File3.txt”的操作,通过循环本身运行有问题的文件(
File3.txt
)";。然后,当我运行代码时,
OutputFile.csv
中显示的唯一数据是
File3.txt
中的数据。但是当它通过循环时,它不会显示在
OutputFile.csv
中。另外,我知道
File3.txt
被发送到循环中,因为我可以看到它在屏幕上用
print$txtfile“,“\n”
打印。我不知道这里发生了什么

另一个问题是,我不认为它是特定于这个特定文件的(可能是)但我不能只解决这一个文件的问题,因为我有130000个文件,我只是碰巧发现这一个文件没有被写入输出文件。因此,可能还有其他文件也没有被写入,尽管没有明显的原因,它们不应该像
File3.txt
那样

可能是因为我在快速连续地处理这么多文件,循环130000个文件,导致了某种I/O问题,导致将内存中的内容写入输出文件时经常出现随机故障?这是我的最佳猜测,但我不知道如何诊断或修复此问题

这是一个很难调试的问题,但我希望这里的人有一些见解,或者见过类似的问题,可以为我提供解决方案


谢谢

我在你的代码中看不到明显的错误。它有点过时了,因为使用和词法文件句柄会更好

但是,我建议您通过将间距变量长度设置在第一个值之后,并选择将最后一个变量的长度设置为0,从而使您的正则表达式的限制性稍微降低。我还将输出文件名。然后您可以看到,出于任何原因,哪些其他文件没有被捕获:

if (m{^007\s+C03(\d{2})\d+\s+(.*)}){
    print OUTFILE "$txtfile $1,VarName,$2\n";
    last;
}

最后,假设每个文件中只有一个
007 C03
,您可以在找到一个后调用
last

您可能需要尝试对@txtfiles列表进行排序,然后尝试系统地查看输出,看看有什么或没有。对于130k个随机顺序的文件,很难找到它们e肯定您错过了一个。Perl应该按照文件在目录中的实际显示顺序为您提供文件,这与像ls这样的用户级命令不同,因此它可能与您预期的不同。

谢谢您的建议。我在
@txtfiles
数组的一部分上运行了我的代码,该数组只有大约20000个文件和conta在整个130000次运行中,我知道有一个文件被排除在外。在这种情况下,
File3.txt
的数据确实显示在输出文件中。因此我认为这与Perl在循环大量文件时丢失内存中的数据有关。您对此有何见解?文件本身很小(>=38MB)。