2017-03-17 4 views
0

長さの可変な行を持つ4GBのテキストファイルがありますが、これはサンプルファイルであり、実動ファイルははるかに大きくなります。私はファイルを読んで、複数行の正規表現を適用する必要があります。Perlは複数行の正規表現で使用するために大きなファイルを読み込みます

マルチライン正規表現でこのような大きなファイルを読み取るにはどうすればよいですか?

私はそれを1行ずつ読むと、私はマルチライン正規表現が正しく動作するとは思わない。 3つの引数の形式でread関数を使用すると、read文で指定した長さのサイズを変更すると、正規表現の結果が変わります。私は、ファイルのサイズが大きすぎて配列やメモリに読み込むことができないと考えています。

ここに私のコード

package main; 
use strict; 
use warnings; 

our $VERSION = 1.01; 
my $buffer; 
my $INFILE; 
my $OUTFILE; 

open $INFILE, '<', ... or die "Bad Input File: $!"; 
open $OUTFILE, '>',... or die "Bad Output File: $!"; 

while (read $INFILE, $buffer, 512 ) { 
    if ($buffer =~ /(?m)(^[^\r\n]*\R+){1}^(B|BREAK|C|CLOSE|D|DO(?! NOT)|E|ELSE|F|FOR|G|GOTO|H|HALT|HANG|I|IF|J|JOB|K|KILL|L|LOCK|M|MERGE|N|O|OPEN|Q|QUIT|R|READ|S|SET|TC|TRE|TRO|TS|U|USE|V|VIEW|W|WRITE|X|XECUTE)(|:).*[^\r\n]/) { 
     print $OUTFILE $&; 
     print $OUTFILE "\n"; 
    } 
} 

close($INFILE); 
close($OUTFILE); 
1; 

は、ここではいくつかのサンプルデータである:上記

^%Z("EUD") 
S %L=%LO,%N="E1" 
^%Z("RT") 
This is data that I don't want the regex to find 
^%Z("EXY") 
X ^%Z("EW2"),^%Z("ELONG"):$L(%L)>245 S %N="E1" Q:$L(%L)>255 X ^%ZOSF("EON") S DX=0,DY=%EY,X=%RM+1 X ^%ZOSF("RM"),XY K %EX,%EY,%E1,%E2,DX,DY,%N Q 
^%Z("F12") 
S %A=$P(^DIC(9.8,0),"^",3)+1,%C=$P(^(0),"^",4)+1 X "F %=0:0 Q:'$D(^DIC(9.8,%A,0)) S %A=%A+1" S $P(^DIC(9.8,0),"^",3,4)=%A_"^"_%C,^DIC(9.8,%A,0)=%X_"^R",^DIC(9.8,"B",%X,%A)="" 
^%Z("F2") 
S %=$H>21549+$H-.1,%Y=%\365.25+141,%=%#365.25\1,%D=%+306#(%Y#4=0+365)#153#61#31+1,%M=%-%D\29+1,%DT=%Y_"00"+%M_"00"+%D,%D=%M_"/"_%D_"/"_$E(%Y,2,3) 

線は(ライン1及び2と共に移動し、3および4など)構文的に、対になっています。

^%Z("RT") 
This is data that I don't want the regex to find 
+3

複数行の正規表現を使用してDSL(ドーマン固有の言語)を解析しようとしているようです。これは、形式が広く変わる可能性があるため、ほとんど常にひどい考えです。これは[XY問題](http://xyproblem.info)のように見えますが、ほとんど正規のものではない場合、正規表現が正しいツールであると考えるウサギの穴が消えてしまいました。あなたがすべきことは、究極の目的の説明とともに、入力の代表的なサンプルを含めるようにあなたの質問を編集することです。 –

+1

後で拡張してより正確な解析を行うためには複雑なので、[Pegex](https://metacpan.org/pod/distribution/Pegex/lib/Pegex.pod)を使用してパーサーを構築することをお勧めします。 (Pegexを学び、文法規則を書く必要がありますが)後で自分自身を支払う可能性があります... – jm666

+0

[私の質問に誰かが答えたときにどうすればよいですか?](http://スタックオーバーフロー。com/help/someone-answers) – zdim

答えて

2

質問はDSLを解析については明らかであり、一般的な正規表現でそのための適切なツールではないようです:私は以外のペアのすべてだ上記のデータでは、特定のペアを見つける必要があります。クイック検索では、pages of CPAN modulesと投稿がthis articleの場合を除き、受け入れられたアプローチの簡単なリストは得られませんでした。最良のアプローチを見つけることは確かに最初のステップです。

しかし、以下はタイトルと明確な説明に記載されている質問に対する答えです。処理される単位が不明な行数に広がる非常に大きなファイルを解析する方法。


「バッファ」を組み立てて確認してください。試合を見つけたら、それを処理しクリアしてください。

たとえば、変数に行を付けて検査します(正規表現を使用すると一致するようにします)。いったんプロセスに合致し、変数を消去したら、続けてください。

my $unit; 
while (<$fh>) { 
    # chomp;  # if suitable 
    $unit .= $_; 

    if (test_unit($unit)) { 
     # process ... 
     $unit = undef; 
    } 
} 

test_unitは、アセンブルされたユニットを処理するかどうかを決めるコードのプレースホルダです。それが正規表現である場合、それは(qr in perlopを参照)my $re = qr/.../;、ループの前に定義することができ、その後、問題のif ($unit =~ $re)

と、ループ内のテストノートは行が対になって処理されると述べているが、それがでclarificatedされます後続の行が必ずしも対にならないというコメント。したがって、行のペアを処理することはできません。

+0

ペアの構文が一貫していないため、ファイル内に他のデータ構造が含まれています。正規表現は私が必要とする複数の行のペアを見つけ、他のすべてのものに渡すので、データの不可解な構造を混乱させる場合に備えてデータを操作しないようにする必要があります。バッファアプローチのコードスニペットを提案できますか? – Intrinsic

+0

@本質的にはわかります。それから、パッチラインとチェックを続けてください。そうすれば、一度に(おそらく)小さな塊しか記憶に残らず、わたしは理解しているとおり、あなたが望むものを正確に行うことができます。 ([@Jim Garrison](http://stackoverflow.com/users/18157/jim-garrison)のコメントによれば、全体のアプローチを他のものに置き換えることができない限り、私はそれを知らない。タイトルおよび明確な声明へ) – zdim

+0

@Intrinsicあなたの説明と他のコメントのステートメントに更新されました。 – zdim

関連する問題