2017-03-22 8 views
1

私の質問はHow do I re.search or re.match on a whole file without reading it all into memory?と同じ質問ですが、perlの代わりにPythonのPerlの正規表現:ファイル全体をメモリに読み込まずに複数行のパターンを検索するにはどうすればよいですか?

質問使用: を私はファイル全体で正規表現を実行することができるようにしたいが、私は持っていないことができるようにしたいのですが私は将来大容量のファイルを扱うかもしれないので、ファイル全体を一度にメモリに読み込むことができます。これを行う方法はありますか?ありがとう!

説明:複数の行にまたがることがあるため、行単位で読み込むことはできません。

私はなぜpythonの代わりにperlを使用していますか?私はperlに切り替える必要があるpythonの正規表現に関する十分な問題にぶつかってきました。私はhttps://pypi.python.org/pypi/regexをインストールしますが、自分の職場ではPythonのインストールディレクトリへの書き込みアクセスを許可していませんし、私のためにそれをインストールするためにITの遅い電子メールチェーンを避けたいと思います。 /またはさらなる権限の問題に対処:)

編集:私は、私は上記のようなパターンを探しています

assign signal0 = (cond1) ? val1 : 
       (cond2) ? val2 : 
          val3; 

assign signal1[15:0] = {input1[7:0], input2[7:0]}; 

assign signal2[34:0] = { 4'b0, 
         subsig0[3:0], 
         subsig1, 
         subsig2, 
         subsig3[18:2], 
         subsig4[5:0] 
         }; 

を探しています例のパターンを、私はセミコロンが表示されるまで、変数の代入をアップすなわち。パターンが複数行かどうかわからないので、正規表現は上記のいずれかにマッチします。おそらく/assign\s+\w+\s+=\s+[^;];/mに似ています。すなわち、セミコロンが表示されるまで続きます。

EDIT2:パターンを開始、中、&終了セクションに分解すると、パターンが最善の戦略になる可能性があります。範囲演算子をいくつか提案したように使用します。

+0

あなたは一致する部分だけを記憶しておきたいですか?その後、完全一致が得られるまで進んで行を読むことができます。一致がなければ最初に行を破棄します。 –

+3

あなたの会社はあなたの開発作業をまったく別の言語に切り替えても大丈夫ですが、モジュールをインストールさせますか? – ThisSuitIsBlackNot

+0

また、[virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/)について聞いたことがありますか?ホームディレクトリに必要なすべてのモジュールをインストールできます。ルートアクセスは必要ありません。 – ThisSuitIsBlackNot

答えて

4

あなたはライン・バイ・ラインを読みながら2つのパターンのすべてを一致させるためにrange operatorを使用することができます。

use strict; 
use warnings 'all'; 

while (<DATA>) { 
    print if /^assign/.. /;/; 
} 

__DATA__ 
foo 
assign signal0 = (cond1) ? val1 : 
       (cond2) ? val2 : 
          val3; 
bar 
assign signal1[15:0] = {input1[7:0], input2[7:0]}; 
baz 
assign signal2[34:0] = { 4'b0, 
         subsig0[3:0], 
         subsig1, 
         subsig2, 
         subsig3[18:2], 
         subsig4[5:0] 
         }; 
qux 

出力:

assign signal0 = (cond1) ? val1 : 
       (cond2) ? val2 : 
          val3; 
assign signal1[15:0] = {input1[7:0], input2[7:0]}; 
assign signal2[34:0] = { 4'b0, 
         subsig0[3:0], 
         subsig1, 
         subsig2, 
         subsig3[18:2], 
         subsig4[5:0] 
         }; 
2

私は(ので、多分私は間違っ、重く考えずに)2つのソリューションを想像することができます

a)に一致する文字の最大数を使用し、1024 1)2倍(2048年)の文字をで読むと言います。 2)一致するようにしてください。 3)前方に1024文字を探します。繰り返す。

b)1行で一致する開始パターンと終了パターンを使用します。中間の部分は後でテストすることができます。このシナリオでは、Perlのフリップフロップ演算子を使用できます。

編集:質問が更新されたので、解決策b)は良いと思われます。

開始パターンは割り当てになり、終了パターンはセミコロンになります。その間のすべてを連結し、後に有効性をテストすることができます。

例:

my $assignment = ""; 
while (<>) { 
    if (/assign\s+\w+\s+=/ .. /;/) { 
     $assignment .= $_; 
    } else { 
     if ($assignment =~ /full regex/) { 
      # do something with the match 
     } 
     $assignment = ""; 
    } 
} 
1

はこちら事前一致パターンによるプログレッシブマッチングを使用する例:

use feature qw(say); 
use strict; 
use warnings; 

my $pre_match = qr{assign\s+\S+\s+=\s+}; 
my $regex = qr{($pre_match[^;]+;)}; 

my $line = ""; 
my $found_start = 0; 
while(<DATA>) { 
    if (!$found_start && /$pre_match/) { 
     $line = ""; 
     $found_start = 1; 
    } 
    if ($found_start) { 
     $line .= $_; 
     if ($line =~ /$regex/) { 
      say "Got match: '$1'"; 
      $found_start = 0; 
      $_ = substr $line, $+[0]; 
      redo; 
     } 
    } 
} 

__DATA__ 
assign signal0 = (cond1) ? val1 : 
       (cond2) ? val2 : 
          val3; 

assign signal1[15:0] = {input1[7:0], input2[7:0]}; 

assign signal2[34:0] = { 4'b0, 
         subsig0[3:0], 
         subsig1, 
         subsig2, 
         subsig3[18:2], 
         subsig4[5:0] 
         }; 

出力

Got match: 'assign signal0 = (cond1) ? val1 : 
       (cond2) ? val2 : 
          val3;' 
Got match: 'assign signal1[15:0] = {input1[7:0], input2[7:0]};' 
Got match: 'assign signal2[34:0] = { 4'b0, 
         subsig0[3:0], 
         subsig1, 
         subsig2, 
         subsig3[18:2], 
         subsig4[5:0] 
         };' 
3

あなたは;をセミコロンと行ずつを読み取るために、入力レコードセパレータ$/を設定することができます。各行は、末尾のセミコロンを含むステートメント上にあります。その後、マッチングは簡単になります。

+0

私は今、私の電話にいますので、例を追加することはできません。 – simbabque

関連する問題