正規表現は実際にどのように機能しますか?


30

エッセイが書かれた文書があるとします。このエッセイを解析して、特定の単語のみを選択します。クール。

正規表現を使用すると、ファイルを行ごとに解析し、単語ごとに一致を検索するよりも高速ですか?もしそうなら、それはどのように機能しますか?各単語を見るよりも速く進むにはどうすればよいですか?


5
(証拠がゼロであることを意味する)正規表現がより高速になると仮定しますが、なぜそうなのかわかりませんか?たぶん、あなたはあなたの仮定を再考すべきです。
pdr

3
したがって、仮定。証拠があったとしても、そうではありませんよね?
lazeR

4
それはポイントではありません。ポイントは、その仮定に導いたものです...あなたはあなたの質問の証拠を必要としませんが、あなたは仮定の推論を必要とします。
ヤンニス

1
エラー、入力文字列のすべての文字が、ステートマシンを次の状態に移動するだけではありません。誰もその操作を遅くする方法がわかりません...
tp1

2
速くなるかどうかはわかりませんが、正規表現を使用する主な理由は、複雑なマッチングパターンの優雅さによるものです。コーディング環境で表現するより良い方法を見つけることはできません。
マントロック

回答:


47

どのように機能しますか?

オートマトン理論ご覧ください

つまり、各正規表現には同等の有限オートマトンがあり、コンパイルして有限オートマトンに最適化できます。関連するアルゴリズムは、多くのコンパイラの本で見つけることができます。これらのアルゴリズムは、awkやgrepなどのUNIXプログラムで使用されます。

ただし、最新のプログラミング言語(Perl、Python、Ruby、Java(およびJVMベースの言語)、C#)は、このアプローチを使用しません。再帰的なバックトラッキングアプローチを使用します。これは、正規表現を、ツリーまたは正規表現のさまざまなサブチャンクを表す一連の構造にコンパイルします。最新の「正規表現」構文は、通常の言語のグループの外にある後方参照を提供し(有限オートマトンでは表現しません)、再帰的なバックトラッキングアプローチで簡単に実装できます。

通常、最適化により、より効率的な状態マシンが生成されます。例:aaaab | aaaac | aaaadを考えてみてください。通常のプログラマは、10分ですぐに(3つの文字列を個別に比較して)シンプルで効率の悪い検索実装を取得できます。しかし、それがaaaa [bcd]と同等であることに気づいた場合、最初の4つの「a」を検索し、5番目の文字を[b、c、d]に対してテストすることにより、より良い検索を行うことができます。最適化のプロセスは、何年も前のコンパイラーのホームワークの1つでした。そのため、最新の正規表現エンジンにも最適化されていると思います。

一方、ステートマシンは、「単純な実装」と比較してより多くのスペースを使用するため、文字列を受け入れる場合にいくつかの利点があります。SQL文字列の引用符をエスケープしないプログラムを考えます。つまり、1)単一引用符で開始および終了します。2)単一引用符は、2つの連続した単一引用符によってエスケープされます。したがって、入力['a' '']は出力[a ']を生成するはずです。状態マシンでは、連続する単一引用符は2つの状態で処理されます。これらの2つの状態は、次の図に示すように、各入力文字が1回だけ処理されるように、入力履歴を記憶する目的に役立ちます。

...
S1->'->S2
S1->*->S1, output *, * can be any other character 
S2->'->S1, output '
S2->*->END, end the current string

だから、私の意見では、些細なケースでは正規表現は遅くなるかもしれませんが、人間が最適化を確実に行うことができないという事実を考えると、通常は手動で作成された検索アルゴリズムよりも高速です。

(文字列の検索のような些細な場合でも、スマートエンジンは状態マップの単一のパスを認識し、その部分を単純な文字列比較に減らして、状態の管理を回避できます。)

フレームワーク/ライブラリの特定のエンジンは、プログラマが通常必要としない他の多くのことを行うため、低速になる場合があります。例:.NETのRegexクラスは、Match、Groups、Capturesを含む多数のオブジェクトを作成します。


2
私はそれを自分でもっとうまく言えなかった。私が追加する唯一のこと:正規表現は怠programmerなプログラマを補うこともできます。あなたがaaaab|aaaac|aaaad対言及した例でaaaa[bcd]。この2つは数学的に同等であり、同じDFAを生成することを明示的に述べる価値があります。したがって、プログラマーは、理にかなった方法で正規表現を表現する自由を与えます(これは一般的な慣習ではありませんが...) ..
リウォーク

おかげで、私が取ったことオートマトンのクラスには、この実際に作られたセンスのおかげ
LAZER

これは、正規表現は行き過ぎである些細な問題?:の一例であるstackoverflow.com/questions/18955099/...
Menelaos Bakopoulos

17

高速なコンピューターを使用しているため、正規表現は高速に見えます。

1 MIPSが高速コンピューターであった1980年代に戻って、正規表現は遅くてbigく、計算集約的であるため、心配、懸念、研究のかなり大きな領域でした。巧妙なアルゴリズム開発が続いて助けられました-しかし、最近ではすべての実用的な目的のために、高速マシンがひび割れを紙で覆っているという奇跡を見ています。


2
単語を1つだけ探している場合は、両方の方法が同じです(または正規表現が少し遅くなります)。しかし、複雑な表現(およびかなり大きなサイズのテキスト)が与えられた場合、正規表現はおそらく単純な検索よりも高速になります(単純な検索を単純に記述すると仮定します(常に高速で複雑な検索を記述できます))。今では重要な天気はあまりにも一般的な質問であり、ケースバイケースでそれを見る必要があります。
マーティンヨーク

3
-1。正規表現の理論は50年代にまでさかのぼり、レキシカルアナライザー(および拡張機能により、コンパイラー)の作成に役立ちました。それらは、可能な限り少ない数の状態を(おそらく)使用する非常に効率的な状態マシンを作成します。結果として得られるステートマシンは、手で書くことができるものよりもはるかに高速で複雑なパターンに一致できます。彼らは速いので、彼らは速く見えます。
リウォーク

私の主張を少し見落としているかもしれません。それらは「速い」かもしれませんが、それはすべて相対的です-まだやるべきことがたくさんあります。ここでの他の答えのいくつかは、同様に読書を負担します。
すぐに

この回答は質問に関連していますか?そして、どのように13 upvotes?
サダナンド

7

なぜ彼らは文書を検索するよりも速いと思いますか?

あなたができるいくつかのトリックがあります。Aで始まりBで終わる10文字の単語を検索する場合、Aを見つけ、さらに9桁上の文字がBでない場合、一部をスキップできます。Knuth–Morris–Prattアルゴリズムを参照してください


5

正規表現を高速化するものは何ですか?

実際、そうではありません。そんなにない。それは私たちのほとんどが気づくほど遅くないということです。昔の遅い時代に、それははるかに顕著でした。

また、すべての仕事に適したツールではありませんハンマーです。


+1のおかげで芸術のその特定の仕事を私に思い出させるために...
ヤニス

5

ほとんどのライブラリは、多くの開発者が長年にわたってパフォーマンスを最大限に引き出すためにライブラリを最適化した結果であるため、RegEx は作成するコードに比べて比較的高速です。1人の個人がそれを自分の検索コードで複製することは困難です。


4
s / squeak / squeeze /?
ペテルトレック

4

あなたの基本的な前提は間違っています。

正規表現は、単純な検索より常に高速であるとは限りません。それはすべてコンテキストに依存します。それは、表現の複雑さ、検索されるドキュメントの長さ、および多くの要因に依存します。

起こるのは、正規表現が単純なパーサーにコンパイルされることです(これには時間がかかります)。したがって、ドキュメントが小さい場合、この余分な時間がメリットを上回ります。また、式が単純な場合、正規表現は利点をもたらしません。

式が複雑で、ドキュメントが十分に大きい場合、いくつかの利点が得られます。これが正規表現の高速化を検討するのに十分なほど重要であるかどうかは、検索にどれだけの労力をかけるかによって大きく異なります(また、正規表現には、自分では考えられなかった最適化がライブラリによって提供される場合があります)。

私が言いたいのは、一般化された包括的な回答はないということです。特定の式(および既知のドキュメントサイズ)があれば、その式が単純な検索よりも速いかどうか(およびその理由)についてはい/いいえの答えを導き出すことができます。

正規表現の本当の利点は、それらの書き方を理解すると、複雑な検索を簡潔に表現できることです。これは一般化された形式であるため、一般的な場合に便利な方法で検索できるツールを作成できます。通常、少なくとも単純な検索と同じくらい高速です(最小サイズのドキュメントでは、これよりも小さいドキュメントでは、それが遅くても十分に高速であるため、重要ではありません)。


1

一部の高レベル言語(おそらくJavaScript)では、低レベル言語(おそらくC)で実装された正規表現ライブラリを使用すると、高レベル言語でパーサーロジックを記述するよりも高速になる可能性があります。

もっともらしい-これが実際に当てはまるかどうかはわかりません。


良いですね!それも私が考えたものです。しかし、今日のプロセッサはその前身よりもはるかに高速であるため、コードを効率的に記述した場合、差分を伝えることができることはめったにないと言えます。私は実際、全体の正規表現よりも速い仮説を本当にガガではありません!;-)
user3833732
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.