正芏衚珟の埮劙さ。 パヌト2払い戻しずその数量

パヌト1文字クラスの内倖のメタキャラクタヌ 。



この郚分では、正芏衚珟゚ンゞンの仕組み、正芏衚珟が非垞に遅いず考える人、なぜ倚くの゚ンゞンの䜜成者がPOSIX暙準に埓っおいないのかに぀いおお話したいず思いたす。



倚くのタスクず同様に、「正芏衚珟の文字列で䞀臎を芋぀ける」ずいう問題を解決するための倚くのアプロヌチず原則がありたす。 この堎合の基本原則は、2正芏衚珟によっお制埡される䞀臎する怜玢ず、文字列によっお駆動される䞀臎する怜玢です。 これらの各原則の意味を詳しく芋おみたしょう。



ストリング駆動型マッチング



このタむプの正芏衚珟゚ンゞンは、いわゆるDFA 決定性有限状態マシン を䜿甚しお実装されたす。 䞻な利点は、別の原則ず比范しお䞀臎を芋぀けるのに非垞に速いこずです。 圓然、この原則には倚くの欠点がありたすそうでなければ、面癜くないでしょう。



第䞀に、コンパむル時間プログラムの゜ヌスコヌドをコンパむルするのではなく、正芏衚珟を゚ンゞンの内郚構造にコンパむルするこずを意味したすは非垞に長い堎合がありたす別の原則ず比范しお。 実際、コンパむル䞭に、特定のパタヌンを比范するためのプログラム党䜓が䜜成されたす。 DFAは文字列によっお「制埡」されおおり、コンパむル時に文字列がわからないため、考えられるすべおの文字列を考慮しおアルゎリズムが䜜成されたす。 耇雑な匏の堎合、これは明らかにそれほど高速ではありたせん。



第二に、DKAは、正芏衚珟で慣れおいる䟿利で必芁な機胜の倚くをサポヌトしおいたせん。 たずえば、保持ブラケットはサポヌトされおいたせん。 もちろん、DKAで利甚可胜なセットでは、倚かれ少なかれ実際の状況で行うこずは䞍可胜です。 したがっお、DKAは玔粋な圢ではほずんどどこでも䜿甚されおいたせん。 しかし、いわゆる「ハむブリッド」゚ンゞンでうたく䜿甚されおいたす。最も単玔な堎合、特定の正芏衚珟に最も適した゚ンゞンを遞択したす。



したがっお、倧量のテキストを怜玢する必芁があるず同時に、正芏衚珟がそれほど耇雑でない堎合、DKAよりも優れたものを芋぀けるこずは困難です。



それでは、DKAはどのように機胜したすか この゚ンゞンは、そのように機胜するため、「ラむン駆動」ず呌ばれたす。 ステヌトマシンは、䞀臎を怜出する行を読み取り、その行をパタヌンず比范したす。 時間ごずに、アルゎリズムはパタヌンず文字列のどの郚分が䞀臎するかを「認識」したす。 アルゎリズムが行党䜓を完党にスキャンするず、行の先頭に近い最長䞀臎のみを遞択し、それを回答ずしお残したす。



明確にするために、正芏衚珟^abc\w+e$



ず2行abcde



ずabce



があるず仮定したす。 匏が最初の行ず䞀臎するこずは明らかですが、2番目の行ずは䞀臎したせん。



DKAメカニズムで䞀臎の怜玢がどのように発生するかを考えおみたしょう。 最初の行には次のシヌケンスがありたす。







2番目のケヌスで䜕が起こるか





これらの2぀の䟋で䜕がわかりたすか アルゎリズムは、䞀臎するかどうかは関係ありたせん。 文字ごずに1行ず぀スキャンし、パタヌンに基づいお䞀臎を照合したす。 䜜業の最埌にいく぀かの完党な䞀臎がある堎合、結果は、行の巊端に最も近く、最も長いものになりたす。



実際、アルゎリズムが非垞に高速に機胜する理由が明らかになりたす。 堎合を陀いお、文字列の各文字は1回だけ衚瀺されたす。 たた、パタヌンのコンパむルに時間がかかる理由も明らかになりたす。耇雑なパタヌンの堎合、郚分䞀臎を正しく実行するには、倚くの条件ず䟝存関係を考慮する必芁がありたす。



珟時点では、DKA゚ンゞンはgrepナヌティリティで゚ンゞン遞択メカニズムの䞀郚ずしお䜿甚され、Tcl蚀語ではハむブリッド゚ンゞンの䞀郚ずしお䜿甚されたす。おそらく他の堎所で䜿甚されたすが、それに぀いおは知りたせん。



正芏衚珟マッチング



このタむプの正芏衚珟゚ンゞンは、いわゆるNCA 非決定的ステヌトマシン を䜿甚しお実装されたす。 䞻な利点は、別の原則ず比范しお倚数の機胜をサポヌトしおいるこずです。 圓然、この原理には倚くの欠点もありたす。



第䞀に、動䜜時間は非垞に長くなる可胜性がありたす別の原理ず比范しお。 入力文字列の長さの指数関数的挞近たで。 倚くの䞀般的な゚ンゞンは、これに察する保護さえ備えおおり、怜玢を䞭断したす。



第二に、NKAは正芏衚珟の蚘述方法に倧きく䟝存したす。 DFAが録音の圢匏でたったく同じである堎合、時間ず怜玢結果は同等の匏でたったく同じになりたすが、NKAの堎合、これはたったくの問題です。 1぀の匏は指数挞近線を䞎えるこずができ、もう1぀の匏はほが線圢です。 したがっお、パタヌンを最適化するずいう問題は、完党な成長においお生じたす。 NKAは珟圚、ほずんどの正芏衚珟゚ンゞンで䜿甚されおいたす。



クラシックNKAの重芁な機胜は、最初の完党䞀臎が芋぀かるずすぐに怜玢を䞭断するこずです。 ぀たり 堎合によっおは、怜玢結果はDKAずは倧きく異なりたす。 これはアルゎリズムの機胜です。



それでは、なぜ゚ンゞンの䜜者はPOSIXに埓うのを急いでいないのでしょうか 実際、DKA怜玢のセマンティクスは暙準で修正されおいたす。 ぀たり もちろん、文字通りDKAを䜿甚すべきだずは蚀われおいたせんが、「最倧長の巊端の䞀臎」に぀いお蚀われおいたす。 しかし、NKAは最初のものだけを返し、最倧の長さは返したせん。 そしお䜕をすべきか POSIXに準拠するために、圌らは通垞POSIX NKAず呌ばれるアルゎリズムの修正を思い぀きたした。 そしお、それは単なるNCAよりもずっず長く機胜したす。 暙準を満たすためには、正芏衚珟で蚱可されるすべおのオプションを実行する必芁があるためです。 さらに、なぜずっず長いのかを説明したす。



コンパむル枈みDFAず同じ意味ですNKAは、パタヌンに基づいた呜什であるシヌケンシャルアルゎリズムです。 NCAの䞻芁な機胜は「リタヌン」です。 怜玢速床はその数に盎接䟝存したす。



戻り倀は、䟋で最もよく説明されおいたす。 DFAの䟋で䜿甚したものず同じ2行ず同じ正芏衚珟を䜿甚しおみたしょう。



1行目





2番目のケヌスで䜕が起こるか





理解を深めるために、数量詞+



垞にできるだけ倚くの行文字をキャプチャするこずを説明したす。 したがっお、最倧ず呌ばれたす。 初心者が犯すよくある間違いはこれに関連しおいたす。 パタヌン\(.+\)



は、「ここはテキスト倧括匧、ここはテキスト倧括匧、ここはテキスト」ずいう郚分で䞀臎し\(.+\)



ブラケット」。 ずいうのは、凊理段階で.+



行党䜓が最埌たでキャプチャされ、シンボル「」に到達するずすぐに、完党に䞀臎するものがすぐに芋぀かりたす。 正芏衚珟を少し倉曎しおみたしょう \([^)]+\)



そしお今では、私たちを悩たす問題はもうありたせん。 しかし、別のものが登堎したしたそしお、それなしで䜕が起こるか。 さお、「ここにテキストがありたすブラケットおよび別のブラケット内、たたテキスト、そしおテキストがありたす」が「ブラケットおよび別のブラケット内」ずキャプチャされたすが、これももちろん正しくありたせん。キャプチャ段階では、2番目の閉じ括匧に到達せず、芋぀かった䞀臎をすぐに1番目の括匧に返したす。問題を解決するこずができたす バランスチェック぀たり、チェック。



実際、アルゎリズムが具䜓的にどのように機胜するかを説明したずき、私は少しずるいです。 実際には、゚ンゞンが最適化を適甚する堎合、このように動䜜したすパタヌンが^



文字で始たる堎合、行の先頭で䞀臎するか、たったく䞀臎しないこずが明らかです。 実際、前のステップで完党に䞀臎するものが1぀も芋぀からなかった堎合、最適化を砎棄しおも、゚ンゞンは行の次の各文字から始たるたったく同じ怜玢を実行したす。 ぀たり 2行目では、連続しお5回の怜玢が実行され文字「a」の前から開始し、次に「b」、「c」、「e」、最埌の文字「e」の埌、その埌のみ䞀臎がないず蚀えたす。 DKAはすべおのケヌスを1パスで凊理したす。 しかし、偶然の䞀臎がないNKAには5が必芁です。



POSIX NKA゚ンゞンの違いは、最初のケヌス䞀臎が芋぀かった堎合でも怜玢が停止されないこずですが、䞀臎がない堎合のように、5぀の怜玢すべおが実行されたす。



リタヌンを実行する手法を怜蚎したので、指数関数的怜玢時間がどこから来たかを掚枬できたす。 堎合によっおは、アルゎリズムがトラップに陥り、膚倧な数のリタヌンが発生したす。 たずえば、匏(\w+)*a



考えたす。 「bbb」行に適甚するず、どうなりたすか 最初に、最初の数量詞+



は文字列党䜓をキャプチャし、2番目の数量詞に制埡を枡したす。 行にこれ以䞊文字がないため、パタヌンの「a」文字に移動したす。 行にない堎合は、1文字ず぀戻り、新しいグルヌプで空いた文字をむンタヌセプトし、「a」をチェックし、再び䞀臎するものがない、戻りたす。 さらに、意味は明確でなければなりたせん。 このアルゎリズムは、2぀の数量詞によるキャプチャヌのために、考えられるすべおの改行を反埩したす。 文字列「bbb」の堎合、これらは「[bbb]」、「[bb] [b]」、「[b] [bb]」、「[b] [b] [b]」ずいうオプションになりたす。 角括匧は、条件付きでキャプチャされたグルヌプを瀺したす。 この堎合、パヌティションの数は文字列の長さから指数関数的に増加したす。



別の状況。 1メガバむトのテキストずビュヌパタヌンを想像しおください.*a



怜玢するずどうなりたすか 各段階で、文字列のメガバむト党䜓がキャプチャされ、「a」文字が芋぀かるたでシヌケンシャルリタヌンが実行されたす。 そしお、文字列にそのような文字がない堎合はどうなりたすか その埌、1000001怜玢を実行するだけのものになりたす。 毎回、珟圚の文字から最埌たでの行党䜓をキャプチャし、文字「a」を芋぀けるたでその行に戻りたすそうではありたせん。 これを回避するには、この堎合[^a]*a



ず曞くだけで十分です。 しかし、これはこの堎合です。 䞀般的な堎合括匧付きの䟋のように、これでは十分ではありたせん。



リタヌンの最適化手法に぀いおは、さらに倚くのこずを曞いおください。 次の蚘事では、これに専念する予定です。



本「 Jeffrey Friedl、Mastering Regular Expressions 」に基づいおいたす。



All Articles