0

だから私はhaxeflixelでいくつかのクリーンアップに取り組んでおり、csvマップを検証する必要があるため、正規表現を使用して問題がないかどうかを確認しています(最後のコンマについては言及しないでください。有効なcsvではないことはわかっていますが、それを許可する)、そして私はそれを行うためのまともな正規表現を持っていると思います、そしてそれはフラッシュでうまくいくようですが、c ++がクラッシュし、nekoは私にこのエラーを与えます:pcre_execの実行中にエラーが発生しました....ここに私の正規表現、長くて申し訳ありませんが、どこに問題があるのか​​ わかりません... ^(([ ]*-?[0-9]+[ ]*,?)+\r?\n?)+$ 何が起こっているのか知っている人がいれば、感謝します、ありがとう、ニコ

ps。csvをチェックするための私の正規表現にはおそらくエラーがありますが、私はそれらを理解することができます.

編集:ああ、これがすべての文字列で発生するわけではないことに気付きました。文字列に絞り込んだら、投稿します...チェックしているものについては、基本的にはそこにあることを確認するためだけです奇妙なxmlヘッダー、またはマップファイル内の整数以外の値はありません。基本的にこれを検証する必要があります:

1,1,1,1

1,1,1,1

1,1,1,1

またはこれ:

1,1,1,1,

1,1,1,1,

1,1,1,1,

だがしかし:

xml 何とか何とか>

1,m,1,1

1,1,b,1

1,1,1,1

xml>

(そして、はい、それが有効なxmlではないことは知っています;))

編集:それは奇妙になります:それで、どの文字列がクラッシュするかを判断しようとしていますが、これでも法線マップのクラッシュを説明することはできませんが、明らかに奇妙で、同じ結果になります:

何が起こるか: これは .match() テストに失敗しますが、クラッシュしません:

a

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

これはプログラムをクラッシュさせますが:

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

1,*a*,1,1,1,1,1,1,1,1,1,1,1,1,1
4

1 に答える 1

1

正直なところ、あなたは私が今まで見た中で最悪の正規表現の 1 つを書きました。実際には、可能な限り遅くなるように特別に書かれているようです。私はあなたを怒らせるためではなく、正規表現を書くことをどれだけ学ぶ必要があるかを表現するために書いています (ヒント: 独自の正規表現エンジンを書くことは良い練習になります)。

あなたの問題に行くと、メモリが不足していると思います(非常にメモリ集約的です)。pcre ターゲットでのみ発生する理由はわかりません (neko ターゲットと cpp ターゲットの両方が pcre を使用します)。

私はの線に沿って何かを提案したいと思います

~/^(( *-?[0-9]+ *,)* *-?[0-9]+ *,?\r?\n)*(( *-?[0-9]+ *,)* *-?[0-9]+ *,?\r?\n?)$/

そこの「~/」と最後の「/」は、haxe regexp マーカーです。

私はそれを広範囲にテストしていませんでした。あなたのサンプルで実行しただけですが、それは仕事をするはずです(おそらく少し調整することで)。

また、ヒントとして、正規表現を実行する前にファイルを最初に行に分割することをお勧めします。これにより、メモリの使用量が減り(または、テキストの一部のみをメモリに保持する必要があります)、正規表現が簡素化されます。

とにかくcsvを解析する必要があるため(データで一般的である適切に形成された入力について)、実際に解析しながらすべてのテストを実行する方がはるかに高速である可能性があることにも注意してください。

編集:「なぜそんなに多くのメモリを消費するのか」という質問への答え

これは短いトピックではありません。そのため、独自の正規表現エンジンを作成することを提案しました。実装にはいくつかの違いがありますが、通常、正規表現エンジンは次のように機能すると想像してください。

  1. 正規表現を解析し、すべての可能な状態のグラフを作成します (状態は基本的にシンボル値とそれに続く他のシンボルへのリンクの数です)。
  2. 正規表現の初期状態と一致した文字列の最初の文字へのポインタで構成される、読み取りポインタと状態ポインタのペアのリスト、現在の状態リストを設定します
  3. シンボル文字列の最初のシンボルへの読み取りポインタを設定します
  4. 状態ポインタを正規表現の初期状態に設定します
  5. 現在の状態リストから 1 つのペアを取得し、現在の状態と現在の読み取りポインターとして格納します。
  6. 現在の読み取りポインターの下のシンボルを読み取ります
  7. 現在の州がリンクしている州のシンボルと照合し、一致した州のリストを作成します。
  8. このリストに最終的な正規表現の状態がある場合は、12 に進みます
  9. このリストの各アイテムに対して、次の読み取りポインター (現在の +1) とアイテムのペアを現在の状態リストに追加します。
  10. 現在の状態リストが空の場合、文字列が正規表現と一致しないため、false を返します
  11. 6に行きます
  12. ここでは、一致した正規表現の最終状態で、true を返し、文字列は正規表現に一致します。

もちろん、正規表現エンジンにはいくつかの違いがあり、そのうちのいくつかはいくつかの問題を解決しています。そしてもちろん、それらには疑似シンボル、グループ化もあり、一致した正規表現とグループを格納する必要があり、先読みと後読みがあり、グループ化参照もあり、少し(非常に謙虚な尺度ですが)より複雑になり、もう少し使用する必要があります複雑なデータ構造ですが、主な考え方は同じです。それで、ここにいます。あなたの問題はアルゴリズムからはっきりとわかります。何を一致させたいかについて具体的でないほど、エンジンが同じ部分文字列を状態グラフの異なるパスと一致させる可能性が高くなればなるほど、指数関数的に消費するメモリとプロセッサ時間が増えます。正規表現エンジンが文字列 aaaaaab、ab、aa、aaaaaaaaaa、aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa (Don'

また、一部の正規表現エンジンは、この状況を適切に処理できるように少し異なる方法で処理を行うことに注意する価値がありますが、正規表現を非常に遅くする方法は常に存在します。

もう1つ注意すべきことは、正確なメモリの問題について私が間違っている可能性があることです。この場合、それはプロセッサでもある可能性があり、その前に、システムのメモリ不足ではなく、メモリ/プロセッサの起動に関するエンジンの制限である可能性があります。

于 2014-04-23T13:51:27.477 に答える