2016-04-03 5 views
1

私はRubular.comでテストした正規表現を書いており、4つのマッチが返されました。テスト対象はhttp://pastebin.com/49ERrzJNで、PHPコードは以下のとおりです。何らかの理由で、PHPコードは最初の2つのマッチだけを返します。どのようにすべての4に一致するようにするには?それは貪欲などと関係しているようです。PHP preg_match_all tr​​ouble

$file = file_get_contents('x.txt'); 
preg_match_all('~[0-9]+\s+(((?!\d{7,}).){2,20})\s{2,30}(((?!\d{7,}).){2,30})\s+([0-9]+)-([0-9]+)-([0-9]+)\s+(F|M)\s+(.{3,25})\s+(((?!\d{7,}).){2,50})~', $file, $m, PREG_SET_ORDER); 
foreach($m as $v) echo 'S: '. $v[1]. '; N: '. $v[3]. '; D:'. $v[7]. '<br>'; 
+2

正確に何を抽出しようとしていますか? – Druzion

+0

** ruby​​ **ではrubular.comがありませんか? – Laurel

+0

@Druzion:名前、姓、DOB、性別の中のほとんど – pedmillon

答えて

2

あなたの正規表現は非常にスロウです。 regex101.comで試した後、私はそれが(JSではなく、何らかの理由で)PHPでタイムアウトすることがわかった。私はタイムアウトが約50,000ステップで起こっていることは確かです。実際には、なぜあなたはオンラインのPHP正規表現テスターを使用していないのが理にかなっています。

私はのmemory_limit [デフォルト:]これはあなたの問題の原因であるかどうかわからないんだけど、there is a default memory limit in PHP:

"128M"

[歴:] PHP 5.2.0の前に "8M"あなたはm ultiline修飾子を使用する場合は、PHPで「16Mは、」5.2.0

、あなただけFiに1282個の手順を実行します。この正規表現を使用することができます(私はpreg_match_allは、本質的にgローブ修飾子を追加することを想定します) NDすべての4試合:

^ [0-9]+\s+(((?!\d{7,}).){2,20})\s{2,30}(((?!\d{7,}).){2,30})\s+([0-9]+)-([0-9]+)-([0-9]+)\s+(F|M)\s+(.{3,25})\s+(((?!\d{7,}).){2,50})

実は、私は追加のみ2文字があります。彼らは最初に、アンカー^とリテラルスペースです。

+0

ありがとう、2文字を追加してm修飾子を使用した場合 – pedmillon

+0

パターンの問題はPHPのメモリ制限とは関係ありません。 –

1

長いパターンを書く必要がある場合は、最初に行うことは読みやすくすることです。これを行うには、コメントとフリースペースを許可する冗長モード(x修飾子)を使用し、名前付きキャプチャを使用します。

次に、あなたが探しているものの正確な記述を行う必要があります。

  • あなたの目標は、行全体を取る=>修飾メートルでアンカー^$を使用し、\hクラスを使用(水平な空白のみを含む)\sクラスの代わりに
  • このような非効率的なサブパターン(?:(?!.....).){m,n}を使用して、フィールドに含まれてはならないものを説明する代わりに、フィールドに含まれるものを記述します。
  • 不要なバックトラッキングを避けるために、非キャプチャグループの代わりに必要な場合は、原子グループ(?>...)を使用します。正確な文字クラスを使用して、一般的に
  • は、問題
  • の多くを回避

パターン:

~ 
^ \h*+ # start of the line 
# named captures       # field separators 
(?<VOTERNO>  [0-9]+     ) \h+ 
(?<SURNAME>  \S+ (?>\h\S+)*?   ) \h{2,} 
(?<OTHERNAMES> \S+ (?>\h\S+)*?   ) \h{2,} 
(?<DOB>   [0-9]{2}-[0-9]{2}-[0-9]{4}) \h+ 
(?<SEX>   [FM]      ) \h+ 
(?<APPID_RECNO> [0-9A-Z/]+    ) \h+ 
(?<VILLAGE>  \S+ (?>\h\S+)*   ) 
\h* $ # end of the line 
~mx 

demo

あなたがパターンと間違って行くかを知りたい場合は、あなたが使用することができます関数preg_last_error()