2009-05-04 7 views
4

正規表現検索の目的は、C++ヘッダーファイルからすべてのテンプレートクラスインスタンスを決定することです。検索が文字列にファイル全体をロードすることによって行われるPerl正規表現のマッチから複数のメモリを取得するにはどうすればよいですか?

CMyClass<int> myClassInstance; 

CMyClass2< 
int, 
int 
> myClass2Instacen; 

open(FILE, $file); 
$string = join('',<FILE>); 
close(FILE); 

および次の正規表現は、場合でも、クラスのインスタンスを決定するために使用されるクラスのインスタンスは、次のようなformartedすることができます

$search_string = "\s*\w[^typename].*<(\s*\w\s*,?\n?)*)>\s*\w+.*"; 
$string =~ m/$search_string/; 

問題は、検索がより多くのクラスのインスタンスがファイルに存在するだけにもかかわらず、1本のヒットを返すことです:クラスのインスタンスは、文字列でもっとして1行にまたがります。

regex backreferences変数の1つからこのアプローチを使用してすべてのヒットを得ることは可能ですか?

答えて

3

必要なものは\Gです。最後のマッチの後にあなたの文字列の次のマッチを開始します。ここで

はPerlのドキュメントからのドキュメントです(SOリンクに問題がされ、あなたがコピー&ペーストする必要があります):

http://perldoc.perl.org/perlfaq6.html#What-good-is-「%5cG'・イン・ザ・正規表現%3f

+0

セクションへの直接リンク:http://perldoc.perl.org/perlfaq6.html#What-good-is-%27\G%27-in-a-regular-expression%3f –

7

最初に、ファイルをスラップする場合は、File::Slurpを使用してください。そうすれば、次のことができます:

my $contents = read_file $file; 

read_fileエラーが発生します。

[^ typename]は、文字列 'typename'だけでなく、それらの文字を含む文字列も除外しません。それ以外は、使用しているパターンが一貫して一致するものと一致することは明らかではありませんが、今はそのことについてコメントすることはできません。最後に

、ループ内でグラム修飾子を使用し、1でファイル1内のすべての一致を得るために:

my $source = '3 5 7'; 

while ($source =~ /([0-9])/g) { 
    print "$1\n"; 
} 

今、私はあなたのパターンを見てチャンスがあったことを、私はまだないですここでは[^型名]で行い、それに何の確認角括弧の間の部分をキャプチャするプログラム例はある(それはあなたが上記キャプチャしている唯一のものであるように思わとして):今すぐ

use strict; 
use warnings; 

use File::Slurp; 

my $pattern = qr{ 
    ^
    \w+      
    <\s*((?:\w+(?:,\s*)?)+)\s*> 
    \s* 
    \w+\s*; 
}mx; 

my $source = read_file \*DATA; 

while ($source =~ /$pattern/g) { 
    my $match = $1; 
    $match =~ s/\s+/ /g; 
    print "$match\n"; 
} 

__DATA__ 
CMyClass<int> myClassInstance; 

CMyClass2< 
int, 
int 
> myClass2Instacen; 

C:\Temp> t.pl 
int 
int, int 

、Iあなたが以下を好むだろうと思われる:

my $pattern = qr{ 
    ^
    (
     \w+      
     <\s*(?:\w+(?:,\s*)?)+\s*> 
     \s* 
     \w+ 
    ) 
    \s*; 
}mx; 

C:\Temp> t.pl 
CMyClass<int> myClassInstance 
CMyClass2< int, int > myClass2Instacen 
0

を、私はこのような何かをしたい、


#!/usr/bin/perl -w 
use strict; 
use warnings; 

local(*F); 
open(F,$ARGV[0]); 
my $text = do{local($/);}; 
my (@hits) = $text =~ m/([a-z]{3})/gsi; 

print "@hits\n"; 

この意志は

 
/home/user$ more a.txt 
a bb dkl jidij lksj lai suj ldifk kjdfkj bb 
bb kdjfkal idjksdj fbb kjd fkjd fbb kadfjl bbb 
bb bb bbd i 

、のようなあなたには、いくつかのテキストファイルを持っていると仮定すると正規表現からすべてのヒットをプリントアウト:


/home/user$ ./a.pl a.txt 
dkl jid lks lai suj ldi kjd fkj kdj fka idj ksd fbb 
kjd fkj fbb kad fjl bbb bbd 


と同じアプローチを使用して、問題の具体的な解決策、のように見えるかもしれませんが、当然の


#!/usr/bin/perl -w                           
use strict; 
use warnings; 

my $text = <<ENDTEXT; 
CMyClass<int> myClassInstance; 

CMyClass2< 
int, 
int 
> myClass2Instacen; 


CMyClass35< 
int, 
int 
    > myClass35Instacen; 

ENDTEXT 

my $basename = "MyClass"; 
my (@instances) = $text =~ m/\s*(${basename}[0-9]*\s*\<.*?                 
          (?=\>\s*${basename})                   
          \>\s*${basename}.*?;)/xgsi; 

for(my $i=0; $i<@instances; $i++){ 
    print $i."\t".$instances[$i]."\n\n"; 
} 

はおそらくにもう少し正規表現を微調整する必要がありますあなたのデータにすべてのエッジケースをフィットさせるが、それはかなり良いスタートでなければならない。

+0

open my $ fh、$ ARGV [0] は ローカル(* F)よりも優れています。 open(F、$ ARGV [0]); 例のPerl :: Criticを使用してください。 –

+0

私はPerl :: Criticを私の例(インストールする手間のビット)で試しましたが、私の例ではコメント/警告/エラーは出ません。また、preとcodeブロックが左括弧を正しくエスケープしていないことに気付きました... – si28719e

関連する問題