ホームページ >ウェブフロントエンド >jsチュートリアル >正規表現に関する初心者向けの 30 分間のチュートリアル
正規表現とは正確には何ですか?次の PHP 中国語 Web サイトでは正規表現について紹介しています。 [推奨読書: 正規表現ビデオ チュートリアル ]
文字列を処理するプログラムや Web ページを作成するとき、特定の複雑なルールに一致する文字列を見つける必要があることがよくあります。正規表現は、これらのルールを記述するために使用されるツールです。言い換えれば、正規表現はテキスト ルールを記録するコードです。
Windows/Dos でのファイル検索に使用されるワイルドカード (ワイルドカード)、つまり * と ? を使用した可能性が非常に高いです。特定のディレクトリ内のすべての Word ドキュメントを検索したい場合は、*.doc を検索します。ここで、* は任意の文字列として解釈されます。ワイルドカードと同様に、正規表現もテキストの一致に使用されるツールですが、ワイルドカードよりもニーズを正確に記述することができます。もちろん、複雑になりますが、たとえば、「すべてを検索するために使用される」という正規表現を書くことができます。 0 で始まり、2 ~ 3 桁、ハイフン「-」、最後に 7 桁または 8 桁の文字列。
はじめに
正規表現を学ぶ最良の方法は、例を理解した後、自分で変更して実験することです。以下にいくつかの簡単な例を示し、詳細に説明します。
英語の小説で hi を検索すると仮定すると、正規表現 hi を使用できます。
これは、このような文字列に正確に一致する、ほぼ最も単純な正規表現です。最初の文字は h、最後の文字は i の 2 つの文字で構成されます。通常、正規表現を処理するツールには、大文字と小文字を区別しないオプションが用意されています。このオプションを選択すると、hi、HI、Hi、および hI の 4 つの大文字と小文字のいずれにも一致します。
残念なことに、hi 、history、high など、多くの単語に連続した 2 文字の hi が含まれています。 hi を使用して検索すると、hi here も検索されます。 hi という単語を正確に見つけたい場合は、\bhi\b を使用する必要があります。
\b は、正規表現 (メタキャラクターと呼ぶ人もいます) で指定された特別なコードで、単語の先頭または末尾、つまり単語の境界を表します。通常、英語の単語はスペース、句読点、または改行で区切られますが、\b はこれらの単語区切り文字のいずれにも一致せず、1 つの位置にのみ一致します。
探しているものが hi の後にそれほど遠くない Lucy が続く場合は、\bhi\b.*\bLucy\b を使用する必要があります。
ここで、 . は別のメタ文字であり、改行文字を除く任意の文字に一致します。 * もメタキャラクターですが、文字や位置を表すのではなく、量を表します。これは、式全体を一致させるために、* より前の内容を何度でも繰り返し使用できることを指定します。したがって、.* は、改行を含まない任意の数の文字を合わせて意味します。 \bhi\b.*\bLucy\b の意味は明らかです。最初に単語 hi、次に任意の数の文字 (改行は除く)、そして最後に単語 Lucy です。
他のメタキャラクターを同時に使用すると、より強力な正規表現を構築できます。たとえば、次の例:
0\d\d-\d\d\d\d\d\d\d\d は、0 で始まり、次に 2 つの数字、そして It で始まる文字列と一致します。はハイフン「-」で、最後は 8 桁です (つまり、中国の電話番号です。もちろん、この例は市外局番が 3 桁の状況にのみ一致します)。
\d は、1 桁 (0、または 1、または 2、または...) に一致する新しいメタキャラクターです。 - はメタキャラクターではなく、それ自体、つまりハイフン (またはマイナス記号、ダッシュ、または任意の名前) とのみ一致します。
迷惑な繰り返しを避けるために、この式を 0\d{2}-\d{8} のように書くこともできます。ここでの \d の後の {2}({8}) は、前の \d が連続して 2 回 (8 回) 繰り返されて一致する必要があることを意味します。
正規表現のテスト
正規表現の読み書きが難しいと感じない場合は、あなたが天才か、地球人ではないかのどちらかです。正規表現の構文は、定期的に使用する人にとってもわかりにくい場合があります。正規表現は読み書きが難しく、エラーが発生しやすいため、正規表現をテストするツールを見つける必要があります。
正規表現の詳細は、環境によって異なります。このチュートリアルでは、Microsoft .Net Framework 4.5 での正規表現の動作を紹介します。そのため、私が作成した .Net バージョンのツール レスターを推奨します。ソフトウェアをインストールして実行するには、このページの手順を参照してください。
以下は、Regester を実行しているスクリーンショットです:
メタキャラクター
これで、\b などのいくつかの便利なメタキャラクターはすでにわかりました。 、.、*、および \d などのメタ文字があります。たとえば、\s は、スペース、タブ (Tab)、改行文字、および中国語の全角スペースを含む任意の空白文字に一致します。 \w は、文字、数字、アンダースコア、漢字などに一致します。
さらに例を見てみましょう:
\ba\w*\b は、文字 a で始まる単語に一致します。最初に単語の先頭 (\b)、次に文字 a、次に文字 a で始まる単語に一致します。任意の数の文字または数字 (\w*)、そして最後に単語の終わり (\b)。
\d は 1 つ以上の連続する数字と一致します。これは * に似たメタキャラクタです。違いは、* は任意の回数 (おそらく 0 回) 繰り返されたものと一致するのに対し、1 回以上繰り返されたものと一致することです。
\b\w{6}\b 正確に 6 文字の単語に一致します。
メタキャラクター ^ (数字の 6 と同じキー位置にある記号) と $ はどちらも位置に一致し、\b に似ています。 ^ は探している文字列の先頭に一致し、$ は末尾に一致します。これら 2 つのコードは、入力内容を確認するときに非常に役立ちます。たとえば、Web サイトで QQ 番号を 5 ~ 12 桁にする必要がある場合は、^\d{5,12}$ を使用できます。ここでの
{5,12} は、前に紹介した {2} と似ていますが、{2} は 2 回のみ一致し、それ以上でもそれ以下でもなく、{5,12} の数が繰り返される点が異なります。回は 5 回未満にすることはできず、12 回を超えることはできません。それ以外の場合は一致しません。
^ と $ が使用されているため、入力文字列全体を \d{5,12} と一致させるために使用する必要があります。つまり、入力全体が 5 ~ 12 個の数値である必要があるため、If your QQ と入力すると、数値がこの正規表現と一致する場合、要件を満たします。
大文字と小文字を無視するオプションと同様に、一部の正規表現処理ツールには複数行を処理するオプションもあります。このオプションを選択すると、^ と $ の意味が一致する行の開始と終了になります。
文字エスケープ
メタ文字そのものを見つけたい場合、たとえば . や * を検索する場合、次のように解釈されるため指定できないという問題があります。何か他の意味。このとき、\ を使用してこれらの文字の特別な意味をキャンセルする必要があります。したがって、\ と \* を使用する必要があります。もちろん、\ 自体を見つけるには、\\.
も使用する必要があります。たとえば、deerchao\.net は deerchao.net に一致し、C:\\Windows は C:\Windows に一致します。
Repeat
*、、、{2}、{5,12} を一致させて繰り返すこれまでの方法はすでに見てきました。以下は、正規表現 (*、{5,12} などの数値を指定するコード) 内のすべての修飾子です。
使用例をいくつか示します。繰り返し:
Windows\d は、Windows の後に 1 つ以上の数字が続くものと一致します
^\w は、行の最初の単語 (または文字列全体の最初の単語、一致する意味のいずれか) と一致します。オプションの設定によって異なります)
文字クラス
数値、文字、数字を検索するには、これらの文字セットに対応するメタ文字がすでに存在するため、空白を使用するのは非常に簡単ですが、必要に応じて何をすべきか事前に定義されたメタキャラクタ (母音 a、e、i、o、u など) を持たない文字セットと一致する場合は一致しますか?
これは非常に簡単で、 [aeiou] は英語の母音に一致し、 [.?!] は句読点 (. or? or!) に一致するように、角かっこで囲むだけで済みます。
[0-9] で表される意味は \d: 1 桁とまったく同じです。同様に、[a-z0-9A-Z_] も完全に同等です。 \w (英語のみを考慮した場合)。
これについて分析してみましょう。最初にエスケープ文字 \( (0 回または 1 回出現する可能性があります) (?)、次に 0、その後に 2 つの数字 (\d{2 }) が続きます。 ) または - またはスペース (1 回出現するかどうか) のいずれか (?)、最後に 8 桁の数字 (\d{8})。
分岐条件
残念ながら、今の式は、010)12345678 や (022-87654321 など) のような「間違った」形式にも一致する可能性があります。この問題を解決するには、分岐条件を使用する必要があります。正規表現の分岐条件は、いずれかのルールが一致した場合に、異なるルールを | で区切るという方法です。例を見てください:
0\d{2}-\d{8}|0\d{3}-\d{7} この式は、ハイフンで区切られた 2 つの電話番号に一致します。番号: 1 つは 3 桁の市外局番と 8 桁の市内番号 (010-12345678 など)、もう 1 つは 4 桁の市外局番と 7 桁の市内番号 (0376-2233445) です。 - ]?\d{8}|0\d{2}[- ]?\d{8} この式は、3 桁の市外局番を持つ電話番号と一致します (市外局番は括弧で囲むことができます)、または No 、市外局番と市外局番はハイフンまたはスペースで区切ることも、区切らなくてもかまいません。分岐条件を使用してこの式を拡張し、4 桁の市外局番
もサポートするようにすることができます。 \d{5. }-\d{4}|\d{5} この式は、米国の郵便番号と一致するために使用されます。米国の郵便番号の規則は 5 桁、または 9 桁で区切られています。この例は問題を示す可能性があるため、\d{5}|\d{5}-\d{4 に変更する場合は、各条件の順序に注意してください。 5 桁の郵便番号 (および 9 桁の郵便番号の最初の 5 桁) を照合する理由は、分岐条件を照合するときに、特定の分岐の場合に各条件が左から右にテストされるためです。
グループ化
単一の文字を繰り返す方法についてはすでに述べましたが、次の場合は、次のようになります。複数の文字を繰り返したい場合はどうすればよいですか? 括弧を使用して部分式 (グループ化とも呼ばれます) を指定し、この部分式の繰り返し数を指定することもできます (will.後で紹介します) .
(\d{1,3}\.){3}\d{1,3} は、単純な IP アドレス一致式です。この式を理解するには、次の順序で分析してください。 \d{1,3} は 1 ~ 3 桁の数値に一致し、(\d{1,3}\.){3} は 3 桁の数値に加えて英語 ピリオド(全体がグループ)を 3 回繰り返し、最後に 1 ~ 3 桁の数字(\d{1,3})を追加します。
残念ながら、これは不可能な IP アドレス 256.300.888.999 にも一致します。算術比較を使用できる場合は、この問題を簡単に解決できる可能性がありますが、正規表現では数学関数が提供されないため、正しい IP アドレスを記述するには、長いグループ化、選択、および文字クラスのみを使用できます:( (2 [0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]| [01] ]?\d\d?)。
この式を理解する鍵は、2[0-4]\d|25[0-5]|[01]?\d\d? を理解することです。ここでは詳しく説明しません。あなたはそれを自分で行うことができます。その意味を分析できるはずです。
反意語
簡単に定義できる文字クラスに属さない文字を検索する必要がある場合があります。たとえば、数字以外の文字を検索する場合は、反意語を使用する必要があります:
例: \S は、空白文字を含まない文字列と一致します。
後方参照
括弧を使用して部分式を指定した後、この部分式に一致するテキスト (つまり、このグループによってキャプチャされたコンテンツ) を式または他のプログラムで使用できます。デフォルトでは、各グループには自動的にグループ番号が付けられます。ルールは、グループの左括弧をマークとして左から右に、最初に表示されるグループのグループ番号は 1、2 番目のグループのグループ番号は 2、そしてなどのアナロジー。
後方参照は、前のグループに一致するテキストを繰り返し検索するために使用されます。たとえば、\1 はグループ 1 に一致するテキストを表します。わかりにくいですか?例を参照してください:
\b(\w )\b\s \1\b は、go go や kitty kitty などの繰り返しの単語と一致させるために使用できます。この式は最初は単語です。つまり、単語の先頭と末尾の間にある複数の文字または数字 (\b(\w)\b) が、番号 1 のグループに取り込まれます。 1 つ以上の空白文字 (\s)、最後にグループ 1 でキャプチャされたコンテンツ (つまり、以前に一致した単語) (\1)。
部分式のグループ名を自分で指定することもできます。部分式のグループ名を指定するには、次の構文を使用します: (? 括弧を使用する場合、多くの特殊な目的の構文が使用されます。最も一般的に使用されるものの一部を以下に示します。 ゼロ幅アサーション 次の 4 つは、何かが発生したときを見つけるために使用されます (これらの内容ではありません)。 ) の前後、つまり、特定の条件 (つまりアサーション) を満たす必要がある位置を指定するために \b,^,$ のように使用されるため、ゼロ幅アサーションとも呼ばれます。例を使用して説明するのが最適です。 (?=exp) は、ゼロ幅のポジティブ予測先読みアサーションとも呼ばれ、式 exp が出現する位置の後に一致する可能性があることを表明します。 。たとえば、\b\w (?=ing\b) は、ing で終わる単語の先頭部分 (ing 以外) に一致します。たとえば、「I'm sing while you're dance.」を検索すると、一致します。歌い踊る。 。 (? 非常に長い数値の 3 桁ごとにカンマを追加する場合 (もちろん、右から追加します)、次のように先頭にカンマを追加する必要がある部分を見つけることができます: ( (( ? 次の例では、両方のアサーションを使用しています: (? 否定的なゼロ幅アサーション 特定の文字ではない文字、または特定の文字クラス (反意語) に属さない文字を検索する方法については前述しました。しかし、特定の文字が表示されないことを確認したいだけで、その文字と一致させたくない場合はどうすればよいでしょうか?たとえば、文字 q が出現するが、q の後に文字 u が続かない単語を検索したい場合は、これを試すことができます: \b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的单词。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为[^u]总要匹配一个字符,所以如果q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w*\b将会匹配下一个单词,于是\b\w*q[^u]\w*\b就能匹配整个Iraq fighting。负向零宽断言能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:\b\w*q(?!u)\w*\b。 零宽度负预测先行断言(?!exp),断言此位置的后面不能匹配表达式exp。例如:\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字;\b((?!abc)\w)+\b匹配不包含连续字符串abc的单词。 同理,我们可以用(? 一个更复杂的例子:(?).*(?=)匹配不包含属性的简单HTML标签内里的内容。(?)指定了这样的前缀:被尖括号括起来的单词(比如可能是),然后是.*(任意的字符串),最后是一个后缀(?=)。注意后缀里的\/,它用到了前面提过的字符转义;\1则是一个反向引用,引用的正是捕获的第一组,前面的(\w+)匹配的内容,这样如果前缀实际上是的话,后缀就是了。整个表达式匹配的是和之间的内容(再次提醒,不包括前缀和后缀本身)。 注释 小括号的另一种用途是通过语法(?#comment)来包含注释。例如:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)。 要包含注释的话,最好是启用“忽略模式里的空白符”选项,这样在编写表达式时能任意的添加空格,Tab,换行,而实际使用时这些都将被忽略。启用这个选项后,在#后面到这一行结束的所有文本都将被当成注释忽略掉。例如,我们可以前面的一个表达式写成这样: 贪婪与懒惰 当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。 有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧: a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。 处理选项 上面介绍了几个选项如忽略大小写,处理多行等,这些选项能用来改变处理正则表达式的方式。下面是.Net中常用的正则表达式选项: 一个经常被问到的问题是:是不是只能同时使用多行模式和单行模式中的一种?答案是:不是。这两个选项之间没有任何关系,除了它们的名字比较相似(以至于让人感到疑惑)以外。 平衡组/递归匹配 有时我们需要匹配像( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构,这时简单地使用\(.+\)则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式,懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等,比如( 5 / ( 3 + 2 ) ) ),那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的,配对的括号之间的内容呢? 为了避免(和\(把你的大脑彻底搞糊涂,我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把xx 这里需要用到以下的语法构造: (?'group') 把捕获的内容命名为group,并压入堆栈(Stack) (?'-group') 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败 (?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分 (?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败 我们需要做的是每碰到了左括号,就在压入一个"Open",每碰到一个右括号,就弹出一个,到了最后就看看堆栈是否为空--如果不为空那就证明左括号比右括号多,那匹配就应该失败。正则表达式引擎会进行回溯(放弃最前面或最后面的一些字符),尽量使整个表达式得到匹配。 平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配嵌套的 上边已经描述了构造正则表达式的大量元素,但是还有很多没有提到的东西。下面是一些未提到的元素的列表,包含语法和简单的说明。你可以在网上找到更详细的参考资料来学习它们--当你需要用到它们的时候。如果你安装了MSDN Library,你也可以在里面找到.net下正则表达式详细的文档。 (?<= # 断言要匹配的文本的前缀
<(\w+)> # 查找尖括号括起来的字母或数字(即HTML/XML标签)
) # 前缀结束
.* # 匹配任意文本
(?= # 断言要匹配的文本的后缀
<\/\1> # 查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签
) # 后缀结束
< #最外层的左括号
[^<>]* #最外层的左括号后面的不是括号的内容
(
(
(?'Open'<) #碰到了左括号,在黑板上写一个"Open"
[^<>]* #匹配左括号后面的不是括号的内容
)+
(
(?'-Open'>) #碰到了右括号,擦掉一个"Open"
[^<>]* #匹配右括号后面不是括号的内容
)+
)*
(?(Open)(?!)) #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果还有,则匹配失败
> #最外层的右括号
以上が正規表現に関する初心者向けの 30 分間のチュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。