最小の正芏衚珟

こんにちは、Habr。

私の名前はVitaliy Kotovで、正芏衚珟に぀いお少し知っおいたす。 カットの䞋で、それらを䜿甚する基本を説明したす。 倚くの理論的な蚘事がこの䞻題に぀いお曞かれおいたす。 この蚘事では、䟋の数に泚目するこずにしたした。 私は、これがこのツヌルの機胜を瀺す最良の方法であるように思えたす。

それらのいく぀かは、PHPたたはJavaScriptのプログラミング蚀語の䟋によっお説明目的で瀺されたすが、䞀般的には、関心のある蚀語に関係なく機胜したす。

タむトルから、この蚘事が最も基本的なレベルを察象ずしおいるこずは明らかです。぀たり、プログラムで正芏衚珟を䜿甚したこずがないか、適切に理解せずに䜿甚した人です。

蚘事の最埌で、正芏衚珟では解決できないタスクず、これに䜿甚するツヌルに぀いお簡単に説明したす。

行こう



゚ントリヌ


正芏衚珟 -テキスト内の郚分文字列たたは郚分文字列を怜玢する蚀語。 怜玢には、文字ずメタキャラクタヌそれ自䜓ではなく、文字のセットを瀺す文字で構成されるパタヌンテンプレヌト、マスクが䜿甚されたす。

これは、怜玢、文字列怜蚌など、倚くの堎合に圹立぀かなり匷力なツヌルです。 その機胜の範囲を1぀の蚘事に収めるこずは困難です。

PHPでは、正芏衚珟の操䜜は䞀連の関数であり、その䞭で最もよく䜿甚されるのは次の関数です。


それらを䜿甚するには、郚分文字列を怜玢たたは眮換するテキストず、怜玢ルヌルを説明する正芏衚珟自䜓が必芁です。

䞀臎関数は、芋぀かった郚分文字列の数を返したす。゚ラヌの堎合はfalseを返したす。 replace関数は、倉曎された文字列/配列、たたぱラヌの堎合はnullを返したす。 結果はブヌル倀に還元され倀が芋぀からなかった堎合はfalse、倀が芋぀かった堎合はtrue、ifたたはassertTrueず組み合わせお結果を凊理できたす。

JSでは、ほずんどの堎合、以䞋を䜿甚する必芁がありたす。


https://regex101.com/ですべおの䟋を参照するこずをお勧めしたす 。 これは、正芏衚珟を操䜜するための䟿利で盎感的なむンタヌフェむスです。

機胜䟋


PHPでは、正芏衚珟は区切り文字で始たり、区切り文字で終わる文字列です。 区切り蚘号の間にあるものはすべお正芏衚珟です。

䞀般的に䜿甚される区切り文字は、スラッシュ「/」、ポンド蚘号「」、およびチルダ「〜」です。 以䞋は、有効な区切り文字を䜿甚したパタヌンの䟋です。


テンプレヌト内でセパレヌタを䜿甚する必芁がある堎合は、バックスラッシュで゚スケヌプする必芁がありたす。 読みやすくするために、テンプレヌトで区切り文字がよく䜿甚される堎合は、このテンプレヌトに別の区切り文字を遞択するこずをお勧めしたす。


JavaScriptでは、正芏衚珟は別個のRegExpオブゞェクトずしお実装され、文字列メ゜ッドに統合されたす。

次のような正芏衚珟を䜜成できたす。

let regexp = new RegExp("", ""); 

たたは、より短いオプション

 let regexp = //; //   

 let regexp = //gmi; //   gmi (  ) 

怜玢する最も単玔な正芏衚珟の䟋

 RegExp: /o/ Text: hello world 

この䟋では、すべおの文字「o」を探しおいたす。

PHPでは、preg_matchずpreg_match_allの違いは、最初の関数が最初の䞀臎を怜出しお怜玢を終了するのに察しお、2番目の関数はすべおの出珟を返すこずです。

PHPコヌド䟋

 <?php $text = 'hello world'; $regexp = '/o/'; $result = preg_match($regexp, $text, $match); var_dump( $result, $match ); 

 int(1) //    , ..     array(1) { [0]=> string(1) "o" //   ,  ,        } 

2番目の関数に぀いおも同じこずを詊みたす。

 <?php $text = 'hello world'; $regexp = '/o/'; $result = preg_match_all($regexp, $text, $match); var_dump( $result, $match ); 

 int(2) array(1) { [0]=> array(2) { [0]=> string(1) "o" [1]=> string(1) "o" } } 

埌者の堎合、関数はテキスト内のすべおの出珟を返したした。

同じJavaScriptの䟋

 let str = 'Hello world'; let result = str.match(/o/); console.log(result); 

 ["o", index: 4, input: "Hello world"] 

テンプレヌト修食子


正芏衚珟には、怜玢の動䜜を倉曎する䞀連の修食子がありたす。 これらは、ラテンアルファベットの1文字で瀺され、正芏衚珟の末尟の「/」の埌に配眮されたす。


PHP で䜿甚されるその他の修食子に぀いおは、 こちらをご芧ください 。

JavaScriptでは、 こちら 。

ここで䞀般的な修食子に぀いお読むこずができたす 。

JavaScript修食子を䜿甚した以前の正芏衚珟の䟋

 let str = "hello world \ How is it going?" let result = str.match(/o/g); console.log(result); 

 ["o", "o", "o", "o"] 

通垞のメタキャラクタヌ


非垞に基本的なこずを知るこずができるため、最初の䟋はかなり原始的です。 孊習すればするほど、䟋は珟実に近づきたす。

ほずんどの堎合、どのテキストを解析する必芁があるか事前にわかりたせん。 事前にわかっおいるのはおおよそのルヌルセットのみです。 SMSのPINコヌド、レタヌでのメヌルなど。

最初の䟋では、テキストからすべおの数倀を取埗する必芁がありたす。

 : “,   1528.  .” 

任意の番号を遞択するには、「[0123456789]」を指定しおすべおの番号を収集する必芁がありたす。 Shorterは「[0-9]」のように蚭定できたす。 すべおの数字にメタ文字「\ d」がありたす。 同じように機胜したす。

しかし、正芏衚珟「/ \ d /」を指定するず、最初の数字のみが返されたす。 もちろん、「g」修食子を䜿甚するこずもできたすが、この堎合、各桁は新しいオカレンスず芋なされるため、配列の個別の芁玠ずしお返されたす。

郚分文字列を単䞀の出珟ずしお衚瀺するために、プラス蚘号「+」ずアスタリスク「*」がありたす。 最初のものは、郚分文字列が私たちに適しおいるこずを瀺しおおり、少なくずも1぀の文字がセットに適しおいたす。 2番目は、この文字セットがそうである堎合もそうでない堎合もあり、これは正垞です。 さらに、次のように適切な文字の正確な倀を瀺すこずができたす。「{N}」。Nは適切な量です。 たたは、「{N、M}」のように指定しお、「from」ず「to」を尋ねたす。

これを念頭に眮いたいく぀かの䟋がありたす。

 : “     2   .”     . RegExp: “/\d/” 

 : “ : 24356”  “   .”     ,   . RegExp: “/\d*/” 

 : “  89091534357”    11 ,  FALSE,   . RegExp: “/\d{11}/” 

ほが同じ方法で、私たちは手玙を扱いたす。手玙があるこずを忘れないでください。 これは、文字を蚭定する方法です。


キリル文字を䜿甚するず、指定された範囲は異なる゚ンコヌディングに察しお異なる動䜜をしたす。 たずえば、Unicodeでは、文字「」はこの範囲に含たれたせん。 詳现に぀いおはこちらをご芧ください 。

いく぀かの䟋

 : “  ”  “  ”     “”,   “”. RegExp: “/[--]+/” 

このような匏は、文に含たれおいるすべおの単語を遞択し、キリル文字で蚘述されたす。 3番目の単語が必芁です。

文字ず数字に加えお、次のような重芁な蚘号も䜿甚できたす。


前の䟋はよりシンプルになりたした。

 : “  ”  “  ”    “”,  “”. RegExp: “/[--]+$/” 

怜玢ワヌドが最埌であるこずが確実にわかっおいる堎合、「$」を入力するず、䜜業の結果は文字セットのみになり、その埌に行の終わりが来たす。

行の先頭ず同じこず

 : “ ”  “ ”    “”,  “”. RegExp: “/^[--]+/” 

メタキャラクタヌをさらに理解する前に、「^」蚘号を個別に説明する必芁がありたす。これは、2぀の䜜品に䞀床に行くためですこれにより、より興味深いものになりたす。 堎合によっおは、行の始たりを瀺したすが、吊定の堎合もありたす。

これは、自分に合った文字よりも自分に合っおいない文字を指定する方が簡単な堎合に必芁です。

私たちに合った文字セットをコンパむルしたずしたす“ [a-z0-9]”小さなラテン文字たたは数字が私たちに合っおいたす。 ここで、これ以倖の文字に満足しおいるずしたす。 「[^ a-z0-9]」のように衚瀺されたす。

䟋

 : “   ”    . RegExp: “[^\s]+” 

すべおの「スペヌスなし」を遞択したす。

したがっお、ここに䞻芁なメタキャラクタヌのリストがありたす。


挔算子[]および


䞊蚘で説明したように、[]を䜿甚しお耇数の文字をグルヌプ化するず掚枬できたす。 したがっお、セットのどのキャラクタヌも私たちに合うず蚀いたす。

䟋

 : “   I dont know, !”     . RegExp: “/[A-Za-z\s]{2,}/” 

ここでは、すべおのラテン文字ずスペヌスをグルヌプ文字[]の間にたずめたす。 {}を䜿甚しお、空のスペヌスから゚ントリを陀倖する少なくずも 2文字の゚ントリに関心があるこずを瀺したした。

同様に、「[^ A-Za-z \ s] {2、}」を反転させるず、すべおのロシア語の単語を取埗できたす。

[]ずは異なり、文字はマヌクされた匏を収集したす。 それらは「キャプチャ」ず呌ばれるこずもありたす。

これらは、遞択したピヌスおそらく、出力内の耇数のオカレンス[]で構成されるを枡すために必芁です。

䟋

 : 'Email you sent was ololo@example.com Is it correct?'    email. 

倚くの解決策がありたす。 以䞋の䟋は、正芏衚珟の嚁力を瀺すおおよそのオプションです。 実際、電子メヌルの正確さを決定するRFCがありたす。 そしお、RFC「芏則」がありたす- ここにいく぀かの䟋がありたす。

スペヌス以倖のすべおを遞択したす電子メヌルの最初の郚分に任意の文字セットを含めるこずができるため、その埌に@蚘号が続き、その埌にピリオドずスペヌス、ピリオド、小文字のラテン文字を陀く...

それでは、行きたしょう


それはそれほど難しくないこずが刀明したした。 これで、メヌルが郚分的に収集されたした。 PHPでのpreg_matchの結果の䟋を考えおみたしょう。

 <?php $text = 'Email you sent was ololo@example.com. Is it correct?'; $regexp = '/[^\s]+@[^\s\.]+\.[az]+/'; $result = preg_match_all($regexp, $text, $match); var_dump( $result, $match ); 

 int(1) array(1) { [0]=> array(1) { [0]=> string(13) "ololo@example.com" } } 

わかった しかし、ドメむンず名前を個別にメヌルで受信する必芁がある堎合はどうでしょうか そしお、なんずかコヌドでさらに䜿甚したすか これが「キャプチャ」が私たちを助ける堎所です。 䟋のように、必芁なものを遞択し、蚘号で囲みたす。

それは

 /[^\s]+@[^\s\.]+\.[az]+/ 

次のようになりたした

 /([^\s]+)@([^\s\.]+\.[az]+)/ 

私達は詊みたす

 <?php $text = 'Email you sent was ololo@example.com. Is it correct?'; $regexp = '/([^\s]+)@([^\s\.]+\.[az]+)/'; $result = preg_match_all($regexp, $text, $match); var_dump( $result, $match ); 

 int(1) array(3) { [0]=> array(1) { [0]=> string(13) "ololo@example.com" } [1]=> array(1) { [0]=> string(5) "ololo" } [2]=> array(1) { [0]=> string(7) "example.com" } } 

䞀臎配列では、れロ゚ントリは垞に正芏衚珟の完党な出珟です。 次に、「キャプチャ」に進みたす。

PHPでは、次の構文を䜿甚しお「キャプチャ」ずいう名前を付けるこずができたす。

 /(?<mail>[^\s]+)@(?<domain>[^\s\.]+\.[az]+)/ 

それから、マッチ配列は連想的になりたす

 <?php $text = 'Email you sent was ololo@example.com. Is it correct?'; $regexp = '/(?<mail>[^\s]+)@(?<domain>[^\s\.]+\.[az]+)/'; $result = preg_match_all($regexp, $text, $match); var_dump( $result, $match ); 

 int(1) array(5) { [0]=> array(1) { [0]=> string(13) "ololo@example.com" } ["mail"]=> array(1) { [0]=> string(5) "ololo" } ["domain"]=> array(1) { [0]=> string(7) "example.com" } } 

これにより、コヌドず芏則性の䞡方が読みやすくなり、すぐに+100になりたす。

実生掻の䟋


新しいパスワヌドを怜玢するParsimの手玙


HTMLコヌドが蚘茉された手玙がありたす。新しいパスワヌドを匕き出す必芁がありたす。 テキストは英語でもロシア語でもかたいたせん。

 : “: <b>f23f43tgt4</b>”  “password: <b>wh4k38f4</b>” RegExp: “(password|):\s<b>([^<]+)<\/b>” 

最初に、パスワヌドの前のテキストには、「たたは」を䜿甚した2぀のオプションがありたす。
任意の数のオプションをリストできたす。

 (password|) 

次に、コロンず1぀のスペヌスがありたす。

 :\s 

次はタグ蚘号bです。

 <b> 

そしお、bタグが閉じおいるこずを瀺すため、「<」蚘号以倖のすべおに関心がありたす。

 ([^<]+) 

私たちは圌を必芁ずしおいるので、私たちは圌を捕囚に包みたす。
次に、終了タグbを䜜成し、「/」文字を゚スケヌプしたす。これは特殊文字であるためです。

 <\/b> 

すべおが非垞に簡単です。

Parsim URL


PHPには、URLを操䜜しおコンポヌネント郚分に解析するのに圹立぀クヌルな機胜がありたす。

 <?php $URL = "https://hello.world.ru/uri/starts/here?get_params=here#anchor"; $parsed = parse_url($URL); var_dump($parsed); 

 array(5) { ["scheme"]=> string(5) "https" ["host"]=> string(14) "hello.world.ru" ["path"]=> string(16) "/uri/starts/here" ["query"]=> string(15) "get_params=here" ["fragment"]=> string(6) "anchor" } 

定期的に同じこずをしたしょうか :)

URLはスキヌムで始たりたす。 私たちにずっお、これはhttp / httpsプロトコルです。 論理的な「たたは」を䜜成できたす。

 (http|https) 

しかし、あなたはカンニングしおこのようにするこずができたす

 http[s]? 

この堎合、蚘号「」は「s」が食べるこずができるこずを意味したすが、そうではありたせん...

次に、「//」がありたすが、「/」文字を゚スケヌプする必芁がありたす䞊蚘を参照。

 “:\/\/” 

次に、「/」蚘号たたは行末にドメむンがありたす。 数字、文字、アンダヌスコア、ダッシュ、ピリオドで構成できたす。

 [\w\.-]+ 

ここで、メタ文字「\ w」、ドット「\」、およびダッシュ「-」を1぀のグルヌプにたずめたす。

次はURIです。 ここではすべおが簡単です。すべおを疑問笊たたは行末に移動したす。

 [^?$]+ 

これで疑問笊になりたす。疑問笊は次の堎合ずそうでない堎合がありたす。

 [?]? 

次に、行末たたはアンカヌの先頭たでのすべお蚘号-この郚分が次のようにならないこずも忘れないでください。

 [^#$]+ 

次はかもしれたせんが、そうでないかもしれたせん

 [#]? 

次に、もしあれば、行末たでのすべお

 [^$]+ 

最終的にはすべおの矎しさが次のようになりたす残念ながら、Habrが行の䞀郚をコメントず芋なさないようにこの郚分を挿入する方法はわかりたせんでした。

 /(?<scheme>http[s]?):\/\/(?<domain>[\w\.-]+)(?<path>[^?$]+)?(?<query>[^#$]+)?[#]?(?<fragment>[^$]+)?/ 

䞻なこずは点滅しないこずです :)

 <?php $URL = "https://hello.world.ru/uri/starts/here?get_params=here#anchor"; $regexp = “/(?<scheme>http[s]?):\/\/(?<domain>[\w\.-]+)(?<path>[^?$]+)?(?<query>[^#$]+)?[#]?(?<fragment>[^$]+)?/”; $result = preg_match($regexp, $URL, $match); var_dump( $result, $match ); 

 array(11) { [0]=> string(61) "https://hello.world.ru/uri/starts/here?get_params=here#anchor" ["scheme"]=> string(5) "https" ["domain"]=> string(14) "hello.world.ru" ["URI"]=> string(16) "/uri/starts/here" ["params"]=> string(15) "get_params=here" ["anchor"]=> string(6) "anchor" } 

圌ら自身の手でのみ、それはほが同じであるこずが刀明したした。



正芏衚珟で解決されないタスク


䞀芋するず、正芏衚珟を䜿甚しおテキストを蚘述および解析できるようです。 しかし、残念ながら、これはそうではありたせん。

正芏衚珟は圢匏蚀語の亜皮であり、チョムスキヌ階局では最も単玔な3番目のタむプに属したす。 ここに぀いお。

この蚀語を䜿甚するず、たずえば、文法が埋め蟌たれたプログラミング蚀語の構文を解析できたせん。 たたはHTMLコヌド。

タスクの䟋


スパンがあり、その䞭には他にも倚くのスパンがあり、どれだけの量かはわかりたせん。 この範囲内にあるすべおのものを遞択する必芁がありたす。

 <span> <span>ololo1</span> <span>ololo2</span> <span>ololo3</span> <span>ololo4</span> <span>ololo5</span> <...> </span> 

もちろん、HTMLを解析する堎合、この範囲だけではありたせん。 :)

䞀番䞋の行は、ある時点で、スパン文字ず/スパン文字を「カりント」できず、開始文字ず終了文字が同じ数でなければならないこずを意味したす。 そしお、これたでペアがなかった終了蚘号がブロックを分離する終了蚘号であるこずを「理解」したす。

コヌドず{}文字に぀いおも同じです。

䟋

 function methodA() { function() {<...>} if () { if () {<...>} } } 

このような構造では、正芏衚珟を䜿甚しお、コヌド内の閉じ括匧を初期関数を完了するものず区別するこずはできたせんコヌドがこの関数だけで構成されおいない堎合。

このような問題を解決するには、より高いレベルの蚀語が䜿甚されたす。

おわりに


正芏衚珟の䞖界の基本に぀いおある皋床詳しく話しおみたした。 もちろん、すべおを1぀の蚘事に収めるこずは䞍可胜です。 圌らずのさらなる䜜業は、経隓ずグヌグルの胜力の問題です。

ご枅聎ありがずうございたした。

Source: https://habr.com/ru/post/J343310/


All Articles