0

我有一个包含多行记录的文件。我需要读取该日志文件以获取一组记录并将每个单独的记录写入单独的文件。文件与下面相同..

VMEMBER NAME  CMPJFCB                                                            
V//NGJFCB   JOB (P,KBTB,BB2994),'MVSNBY-CMP',CLASS=A,                    JOB40337
V//           REGION=0M,MSGCLASS=W,NOTIFY=&SYSUID    
v// CYX sss eee
VMEMBER NAME  CMPJFCB                                                            
V//NGJFCB   JOB (P,KBTB,BB2994),'MVSNBY-CMP',CLASS=A,                    JOB40337
V//           REGION=0M,MSGCLASS=W,NOTIFY=&SYSUID    
v
v//
VMEMBER NAME  CMPJFCB                                                            
V//NGJFCB   JOB (P,KBTB,BB2994),'MVSNBY-CMP',CLASS=A,                    JOB40337
V//           REGION=0M,MSGCLASS=W,NOTIFY=&SYSUID    
v
v//
v/*
and so on ...

所以从上面的起点我们知道“VMEMBER NAME”,但我们不知道终点。它可以以“V”或“V//”或任何东西结尾。我尝试使用范围匹配如下

$line =~ m{VMEMBER .. v\/\*}

但问题是最后一个模式(v*),因为我们不确定最后一行记录是什么。请帮忙。

第一组的输出应该是

VMEMBER NAME  CMPJFCB                                                            
V//NGJFCB   JOB (P,KBTB,BB2994),'MVSNBY-CMP',CLASS=A,                    JOB40337
V//           REGION=0M,MSGCLASS=W,NOTIFY=&SYSUID    
v// CYX sss eee

第二组将是

VMEMBER NAME  CMPJFCB                                                            
V//NGJFCB   JOB (P,KBTB,BB2994),'MVSNBY-CMP',CLASS=A,                    JOB40337
V//           REGION=0M,MSGCLASS=W,NOTIFY=&SYSUID    
v
v//

像这样。

4

4 回答 4

4

One option is to set Perl's record separator ($/) to 'VMEMBER NAME', so it effectively chunks the file by that:

use strict;
use warnings;

local $/ = 'VMEMBER NAME';
my $recNum;

while (<>) {
    chomp;

    if (/\S/) {
        open my $fh, '>', "record\_" . ++$recNum . '.txt' or die $!;
        print $fh $/ . $_;
    }
}

Usage: perl logFile

This script creates a set of files, record_1.txt ... record_n.txt, which contains your desired output.

Hope this helps!

于 2013-10-14T17:13:54.617 回答
3

该程序将按照您的要求进行。它期望输入文件的路径作为命令行上的参数,并生成 filesFile_001.txtFile_002.txt直到文件末尾。sprintf如果要更改输出文件名,可以修改使用的格式。

use strict;
use warnings;
use autodie;

my $outfh;
my $n;

while (<>) {
  if (/^VMEMBER/) {
    my $file = sprintf "File_%03d.txt", ++$n;
    open $outfh, '>', $file;
  }
  print $outfh $_ if $outfh;
}

close $outfh if $outfh;
于 2013-10-14T17:36:24.777 回答
2

这是一种方法。

use strict;
use warnings; 

my %hash;
my $counter = 0;
my $group;

open my $fh, '<', 'data1.txt' # <-- The path to your file comes here!.
    or die "can't open data1.txt $1";

while (my $line = <$fh>) {
    if ($line =~ /^VMEMBER/) {
    $group = 'Group Number: ' . $counter++;
    }
    push @{ $hash{ $group } }, $line;
}

#By this point in the script all of your record have been separated in different set.
#As you can see in the output below.  

foreach my $group (sort keys %hash) {
    print "$group\n", @{ $hash{ $group } }, "\n";
} 

输出

Group Number: 0
VMEMBER NAME  CMPJFCB                                                            
V//NGJFCB   JOB (P,KBTB,BB2994),'MVSNBY-CMP',CLASS=A,                    JOB40337
V//           REGION=0M,MSGCLASS=W,NOTIFY=&SYSUID    
v// CYX sss eee

Group Number: 1
VMEMBER NAME  CMPJFCB                                                            
V//NGJFCB   JOB (P,KBTB,BB2994),'MVSNBY-CMP',CLASS=A,                    JOB40337
V//           REGION=0M,MSGCLASS=W,NOTIFY=&SYSUID    
v
v//

Group Number: 2
VMEMBER NAME  CMPJFCB                                                            
V//NGJFCB   JOB (P,KBTB,BB2994),'MVSNBY-CMP',CLASS=A,                    JOB40337
V//           REGION=0M,MSGCLASS=W,NOTIFY=&SYSUID    
v
v//
v/*
于 2013-10-14T16:54:22.877 回答
0

这是我的看法,对我来说效果很好......

open (FILE, "abc.txt" ) || die "can't open file!";

my $reset=0;
my $SD=1;
while (<FILE>) {

if ( m/VMEMBER NAME/){
   if($reset != 0)
   {
    close OUT;
    }
    open(OUT, ">JOBS_$SD.txt") || die ("File could not found! $i");

    $SD++;
    $reset=1;
   }

print OUT $_;   

}
于 2013-10-14T17:09:01.133 回答