正規表現は面倒ですが強力です。学習後に適用すると、効率が向上するだけでなく、絶対的な達成感も得られます。これらの資料を注意深く読み、適用する際に特定の参照を行っている限り、正規表現をマスターすることは問題ありません。
1. はじめに
現在、正規表現は、*nix (Linux、Unix など)、HP およびその他のオペレーティング システム、PHP、C#、Java およびその他の開発環境、さらには多くのアプリケーション ソフトウェアを含む多くのソフトウェアで広く使用されています。正規表現シャドウまで見ることができます。
正規表現を使用すると、強力な機能を簡単な方法で実現できます。シンプルで効果的でありながら強力であるために、正規表現コードはより難しく、習得するのが簡単ではないため、使い始めた後は、特定のリファレンスを参照して使用するのが比較的簡単で効果的です。
例: ^.+@.+..+$
そんな暗号に何度も怯えてしまいました。おそらく多くの人がそのようなコードを怖がってしまうでしょう。この記事を読み続けると、このようなコードを自由に適用できるようになります。
注: ここのパート 7 は、前の内容と多少重複しているように見えますが、その目的は、これらの内容を理解しやすくするために、前の表の部分を再説明することです。
2. 正規表現の歴史
正規表現の「祖先」は、人間の神経系の仕組みに関する初期の研究に遡ることができます。 2 人の神経生理学者、ウォーレン・マカロックとウォルター・ピッツは、これらのニューラル ネットワークを記述する数学的方法を開発しました。
1956年、Stephen Kleeneという数学者は、McCullochとPittsの初期の研究に基づいて「ニューラルネットワークイベントの表現」というタイトルの論文を発表し、正規表現の概念を導入しました。正規表現は、彼が「正規集合の代数」と呼ぶ式を記述するために使用されるため、「正規表現」という用語が付けられています。
その後、この研究は、Unix の主な発明者である Ken Thompson の計算検索アルゴリズムを使用した初期の研究に適用できることが判明しました。正規表現を最初に実際に応用したのは、Unix の qed エディターでした。
残りは、彼らが言うように、私たちが知っているように歴史です。それ以来、正規表現はテキストベースのエディターや検索ツールの重要な部分となってきました。
3. 正規表現の定義
正規表現は、文字列に特定の部分文字列が含まれているかどうかを確認したり、一致する部分文字列を置換したり、文字列から特定の条件を満たす部分文字列を削除したりするために使用できる、文字列の一致パターンを記述します。
ディレクトリをリストする場合、dir *.txt または ls *.txt 内の *.txt は正規表現ではありません。これは、ここでの * の意味が正規表現の * とは異なるためです。
正規表現とは、通常の文字(文字aからzなど)と特殊文字(メタキャラクターと呼ばれます)で構成されるテキストパターンです。正規表現は、文字パターンと検索文字列を照合するテンプレートとして機能します。
3.1 通常のキャラクター
メタキャラクターとして明示的に指定されていないすべての印刷文字と非印刷文字で構成されます。これには、すべての大文字と小文字のアルファベット、すべての数字、すべての句読点、および一部の記号が含まれます。
3.2 非印刷文字
文字の意味
cxはxで指定された制御文字と一致します。たとえば、cM は Control-M または復帰文字と一致します。 x の値は、A ~ Z または a ~ z のいずれかでなければなりません。それ以外の場合、c はリテラルの「c」文字として扱われます。
fはフォームフィード文字と一致します。 x0c および cL に相当します。
nは改行文字と一致します。 x0a および cJ に相当します。
r は復帰文字と一致します。 x0d および cM に相当します。
s は、スペース、タブ、フォーム フィードなどを含む任意の空白文字と一致します。 【fnrtv】に相当。
S は空白以外の任意の文字に一致します。 [^ fnrtv] に相当します。
tはタブ文字と一致します。 x09 および cI に相当します。
vは垂直タブ文字に一致します。 x0b および cK に相当します。
3.3 特殊文字
いわゆる特殊文字は、上記の「*.txt」の * など、特別な意味を持つ文字であり、簡単に言えば、任意の文字列の意味を表します。ファイル名に * が含まれるファイルを検索する場合は、* をエスケープする、つまり * の前に 1 を追加する必要があります。 ls*.txt。正規表現には次の特殊文字があります。
特殊文字の説明
$は入力文字列の終了位置と一致します。 RegExp オブジェクトの Multiline プロパティが設定されている場合、$ は 'n' または 'r' にも一致します。 $ 文字そのものと一致させるには、$ を使用します。
( )は部分式の始まりと終わりを示します。部分式は後で使用するために取得できます。これらの文字と一致させるには、( と ) を使用します。
* 前の部分式と 0 回以上一致します。 * 文字と一致させるには、* を使用します。
+ 前の部分式と 1 回以上一致します。 + 文字と一致させるには、+ を使用します。
.改行文字 n を除く任意の 1 文字と一致します。 . と一致させるには、 を使用します。
[角括弧式の始まりを示します。 [ と一致させるには、[ を使用します。
?前の部分式と 0 回または 1 回一致するか、貪欲でない修飾子を指定します。 ? 文字に一致させるには、? を使用します。
次の文字を特殊文字、リテラル文字、後方参照、または 8 進エスケープ文字としてマークします。たとえば、「n」は文字「n」と一致します。 「n」は改行文字に一致します。シーケンス '' は "" に一致し、'(' は "(" に一致します。
^ は、角括弧式で使用されない限り、入力文字列の先頭と一致します。その場合、文字セットが受け入れられないことを示します。 ^ 文字そのものと一致させるには、^ を使用します。
{修飾子式の始まりをマークします。 { と一致させるには、{ を使用します。
| 2 つの項目から選択を示します。 | と一致させるには、| を使用します。
正規表現の構築は、数式の作成と同じです。つまり、さまざまなメタ文字と演算子を使用して小さな式を結合し、より大きな式を作成します。正規表現のコンポーネントは、単一の文字、文字のコレクション、文字の範囲、文字間の選択、またはこれらすべてのコンポーネントの任意の組み合わせにすることができます。
3.4予選
修飾子は、一致を満たすために正規表現の特定のコンポーネントが何回出現する必要があるかを指定するために使用されます。 * または + または ? または {n} または {n,} または {n,m} の 6 種類があります。
*、+、および ? 修飾子はすべて、できるだけ多くのリテラルと一致するため、それらの後に ? を追加するだけで非貪欲一致または最小限の一致が実現されます。
正規表現の修飾子は次のとおりです:
キャラクター説明
* 前の部分式と 0 回以上一致します。たとえば、zo* は「z」と「zoo」に一致します。 * {0,} に相当します。
+ 前の部分式と 1 回以上一致します。たとえば、「zo+」は「zo」と「zoo」には一致しますが、「z」には一致しません。 + は {1,} と同等です。
? 前の部分式と 0 回または 1 回一致します。たとえば、「do(es)?」は「do」または「does」の「do」と一致します。 ? {0,1} に相当します。
{n}nは負でない整数です。特定の回数 n 回一致します。たとえば、「o{2}」は「Bob」の「o」とは一致しませんが、「food」の両方の「o」には一致します。
{n,}nは負でない整数です。少なくとも n 回一致します。たとえば、「o{2,}」は「Bob」の「o」とは一致しませんが、「foooood」のすべての「o」と一致します。 「o{1,}」は「o+」と同等です。 「o{0,}」は「o*」と同等です。
{n,m}m と n は両方とも非負の整数で、n
3.5ロケーター
文字列または単語の境界を表すために使用されます。^ と $ はそれぞれ文字列の先頭と末尾を指し、b は単語の前または後ろの境界を表し、B は単語以外の境界を表します。修飾子はロケーターでは使用できません。
3.6 選ぶ
すべての選択範囲を括弧で囲み、隣接する選択範囲を | で区切ります。ただし、括弧を使用すると、関連する一致がキャッシュされるという副作用が生じます。この場合、最初のオプションの前に ?: を使用すると、この副作用を排除できます。
このうち、?: は非キャプチャ要素の 1 つで、他の 2 つの非キャプチャ要素は ?= と ?! です。これら 2 つは前方参照であり、括弧内の正規表現と一致します。検索文字列は、式パターン内の任意の位置で一致します。これは、正規表現パターンと一致しない任意の先頭位置で検索文字列と一致する否定先読みです。
3.7 バックリファレンス
正規表現パターンまたはパターンの一部を括弧で囲むと、キャプチャされた各部分一致が正規表現パターンの左から右に保存されます。部分一致が格納されるバッファには、1 から始まり、最大 99 個の部分式まで連続した番号が付けられます。各バッファには、「n」を使用してアクセスできます。n は、特定のバッファを識別する 1 桁または 2 桁の 10 進数です。
非キャプチャメタ文字「?:」、「?=」、または「?!」を使用して、関連する一致の保存を無視できます。
4. 各種演算子の演算優先順位
同じ優先度の操作は左から右に実行され、異なる優先度の操作は高から低に実行されます。さまざまな演算子の優先順位は高いものから低いものまで次のとおりです:
オペレーターの説明
エスケープ文字
()、(?:)、(?=)、[]丸括弧と角括弧
*、+、?、{n}、{n,}、{n,m} 修飾子
^、$、任意のメタ文字の位置と順序
|「OR」演算
5.全記号の説明
キャラクター説明
次の文字を特殊文字、リテラル文字、後方参照、または 8 進エスケープ文字としてマークします。たとえば、「n」は文字「n」と一致します。 「n」は改行文字に一致します。シーケンス '' は "" に一致し、"(" は "(" に一致します。
^は入力文字列の先頭と一致します。 RegExp オブジェクトの Multiline プロパティが設定されている場合、^ は 'n' または 'r' の後の位置にも一致します。
$は入力文字列の終了位置と一致します。 RegExp オブジェクトの Multiline プロパティが設定されている場合、$ は 'n' または 'r' の前の位置にも一致します。
* 前の部分式と 0 回以上一致します。たとえば、zo* は「z」と「zoo」に一致します。 * {0,} に相当します。
+ 前の部分式と 1 回以上一致します。たとえば、「zo+」は「zo」と「zoo」には一致しますが、「z」には一致しません。 + は {1,} と同等です。
? 前の部分式と 0 回または 1 回一致します。たとえば、「do(es)?」は「do」または「does」の「do」と一致します。 ? {0,1} に相当します。
{n}nは負でない整数です。特定の回数 n 回一致します。たとえば、「o{2}」は「Bob」の「o」とは一致しませんが、「food」の両方の「o」には一致します。
{n,}nは負でない整数です。少なくとも n 回一致します。たとえば、「o{2,}」は「Bob」の「o」とは一致しませんが、「foooood」のすべての「o」と一致します。 「o{1,}」は「o+」と同等です。 「o{0,}」は「o*」と同等です。
{n,m}m と n は両方とも非負の整数で、n
文字が他のリミッター (*、+、?、{n}、{n,}、{n,m}) の直後にある場合、一致パターンは非貪欲です。非貪欲モードは検索文字列の可能な限り少ない部分と一致しますが、デフォルトの貪欲モードは検索文字列の可能な限り多くの部分と一致します。たとえば、文字列「oooo」の場合、「o+?」は単一の「o」に一致しますが、「o+」はすべての「o」に一致します。
.「n」を除く任意の 1 文字と一致します。 「n」を含む任意の文字と一致するには、「[.n]」のようなパターンを使用します。
(pattern) pattern と一致し、この一致を取得します。取得された一致は、VBScript の SubMatches コレクションまたは JScript の $0 ~ $9 プロパティを使用して、生成された Matches コレクションから取得できます。括弧文字と一致させるには、「(」または「)」を使用します。
(?:pattern) は pattern に一致しますが、一致結果が得られません。これは、非取得一致であり、後で使用するために保存されないことを意味します。これは、「または」文字 (|) を使用してパターンの一部を結合する場合に便利です。たとえば、「industr(?:y|ies)」は「industry|industries」より短い式です。
(?=pattern) 前方参照。文字列一致パターンの先頭にある検索文字列と一致します。これは非フェッチ一致です。つまり、後で使用するために一致をフェッチする必要はありません。たとえば、「Windows (?=95|98|NT|2000)」は、「Windows 2000」の「Windows」には一致しますが、「Windows 3.1」の「Windows」には一致しません。プリフェッチでは文字は消費されません。つまり、一致が発生した後、次の一致の検索は、プリフェッチを含む文字の後に開始されるのではなく、最後の一致の直後に開始されます。
(?!pattern) 否定検索。pattern に一致しない文字列の先頭にある検索文字列と一致します。これは非フェッチ一致です。つまり、後で使用するために一致をフェッチする必要はありません。たとえば、「Windows (?!95|98|NT|2000)」は、「Windows 3.1」の「Windows」と一致しますが、「Windows 2000」の「Windows」とは一致しません。プリフェッチは文字を消費しません。つまり、一致が発生した後、次の一致の検索は、プリフェッチを含む文字の後に開始されるのではなく、最後の一致の直後に開始されます
x|y は x または y に一致します。たとえば、「z|food」は「z」または「food」と一致します。 '(z|f)ood' は、「zood」または「food」と一致します。
[xyz]文字セット。含まれている文字のいずれかと一致します。たとえば、「[abc]」は「plain」の「a」と一致します。
[^xyz] 負の値の文字セット。含まれていない任意の文字と一致します。たとえば、「[^abc]」は「plain」の「p」と一致します。
[a-z] 文字範囲。指定された範囲内の任意の文字と一致します。たとえば、「[a-z]」は、「a」から「z」の範囲内の任意の小文字のアルファベット文字と一致します。
[^a-z]負の文字範囲。指定された範囲内にない任意の文字と一致します。たとえば、「[^a-z]」は、「a」から「z」の範囲にない任意の文字と一致します。
b は、単語とスペースの間の位置を指す単語境界に一致します。たとえば、「erb」は「never」の「er」と一致しますが、「動詞」の「er」とは一致しません。
Bは単語以外の境界に一致します。 「erB」は「動詞」の「er」と一致しますが、「never」の「er」とは一致しません。
cxはxで指定された制御文字と一致します。たとえば、cM は Control-M または復帰文字と一致します。 x の値は、A ~ Z または a ~ z のいずれかでなければなりません。それ以外の場合、c はリテラルの「c」文字として扱われます。
dは数字と一致します。 [0-9]に相当します。
Dは数字以外の文字と一致します。 [^0-9] と同等。
fはフォームフィード文字に一致します。 x0c および cL に相当します。
nは改行文字に一致します。 x0a および cJ に相当します。
r は復帰文字と一致します。 x0d および cM に相当します。
s は、スペース、タブ、フォーム フィードなどを含む任意の空白文字と一致します。 【fnrtv】に相当。
S は空白以外の任意の文字に一致します。 [^ fnrtv] に相当します。
tはタブ文字と一致します。 x09 および cI に相当します。
vは垂直タブ文字に一致します。 x0b および cK に相当します。
w は、アンダースコアを含む任意の単語文字に一致します。 「[A-Za-z0-9_]」と同等。
W は単語以外の文字に一致します。 「[^A-Za-z0-9_]」と同等。
xn は n と一致します。n は 16 進数のエスケープ値です。 16 進数のエスケープ値は、正確に 2 桁の長さである必要があります。たとえば、「x41」は「A」と一致します。 「x041」は「x04」および「1」と同等です。 ASCII エンコーディングは正規表現で使用できます。 .
num は num と一致します。ここで、num は正の整数です。取得した一致への参照。たとえば、「(.)1」は、連続する 2 つの同一の文字に一致します。
n は 8 進エスケープ値または後方参照を識別します。 n の前に少なくとも n 個のフェッチされた部分式がある場合、n は後方参照になります。それ以外の場合、n が 8 進数 (0 ~ 7) の場合、n は 8 進数のエスケープ値になります。
nm は、8 進エスケープ値または後方参照を識別します。 nm の前に少なくとも nm 個の取得可能な部分式がある場合、nm は後方参照になります。 nm の前に少なくとも n が取得されている場合、n は後方参照であり、その後にリテラル m が続きます。前述の条件がどちらも当てはまらず、n と m が両方とも 8 進数 (0 ~ 7) である場合、nm は 8 進数のエスケープ値 nm と一致します。
n が 8 進数 (0 ~ 3) で、m と l が両方とも 8 進数 (0 ~ 7) である場合、nml は 8 進数エスケープ値 nml と一致します。
un は n と一致します。n は 4 桁の 16 進数で表される Unicode 文字です。たとえば、u00A9 は著作権記号 (?) に一致します。
6. いくつかの例
正規表現の説明
/b([a-z]+) 1b/gi 単語が連続して出現する位置
/(w+)://([^/:]+)(:d*)?([^# ]*)/URLをプロトコル、ドメイン、ポート、相対パスに解決します
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/章の位置を特定します
/[-a-z]/A から z、合計 26 文字と - 記号。
/terb/ はチャプターに一致しますが、ターミナルには一致しません
/Bapt/ は章に一致しますが、適性は一致しません
/Windows(?=95 |98 |NT )/ は Windows95 または Windows98 または WindowsNT と一致します。一致するものが見つかると、次の検索一致は Windows の後ろから始まります。
7. 正規表現のマッチングルール
7.1 基本的なパターンマッチング
すべては基礎から始まります。パターンは正規表現の最も基本的な要素であり、文字列の特性を記述する文字のセットです。パターンは、通常の文字列で構成される単純な場合もあれば、文字範囲、繰り返し、コンテキストを表すために特殊文字を使用する非常に複雑な場合もあります。例:
^1回
このパターンには特殊文字 ^ が含まれており、パターンが 1 回で始まる文字列にのみ一致することを意味します。たとえば、このパターンは文字列「onceUponatime」には一致しますが、「There Once was a man from NewYork」には一致しません。 ^ 記号が先頭を示すのと同様に、$ 記号は特定のパターンで終わる文字列と一致します。
バケツ$
このパターンは、「誰がこの現金をすべてバケツに入れたか」には一致しますが、「バケツ」には一致しません。文字 ^ と $ が同時に使用される場合、それは完全一致 (文字列がパターンと同じ) を意味します。例:
^バケツ$
文字列「bucket」にのみ一致します。パターンに ^ と $ が含まれていない場合は、そのパターンを含む任意の文字列と一致します。例: パターン
一度
紐付き
かつてニューヨークから来た男がいました
現金をすべてバケツに入れて保管していた人。
一致します。このパターンの文字(o-n-c-e)はリテラル文字、つまり文字そのものを表しており、数字も同様です。句読点や白文字 (スペース、タブなど) など、その他の少し複雑な文字にはエスケープ シーケンスが必要です。すべてのエスケープ シーケンスはバックスラッシュ () で始まります。タブ文字のエスケープ シーケンスは次のとおりです。したがって、文字列がタブ文字で始まるかどうかを検出したい場合は、次のパターンを使用できます:
^t
同様に、「改行」を表すには n を使用し、復帰を表すには r を使用します。他の特殊記号は、バックスラッシュ自体を . で表し、ピリオドを . で表すなど、前にバックスラッシュを付けて使用できます。
7.2 キャラクタークラスター
INTERNET プログラムでは、通常、ユーザー入力を検証するために正規表現が使用されます。ユーザーがフォームを送信するとき、入力された電話番号、住所、電子メール アドレス、クレジット カード番号などが有効かどうかを判断するには、通常のリテラル文字を使用するだけでは十分ではありません。
そのため、必要なパターンを記述するために、より自由な方法、つまり文字クラスターを使用する必要があります。すべての母音文字を表すクラスターを作成するには、すべての母音文字を角かっこで囲みます:
[あああああ]
このパターンは任意の母音文字に一致しますが、表すことができるのは 1 つの文字のみです。次のような文字範囲を表すにはハイフンを使用します:
[a-z] //すべての小文字と一致します
[A-Z] //すべての大文字と一致します
[a-zA-Z] //すべての文字に一致
[0-9] //すべての数字と一致します
[0-9.-] //すべての数字、ピリオド、マイナス記号と一致します
[ frtn ] // すべての白文字と一致します
繰り返しになりますが、これらは 1 つの文字を表すだけであり、非常に重要な文字です。 「z2」、「t6」、または「g7」などの小文字と数字で構成される文字列と一致させたいが、「ab2」、「r2d3」、または「b52」には一致させたくない場合は、次のパターンを使用します:
^[a-z][0-9]$
[a-z]は26文字の範囲を表しますが、ここでは最初の文字が小文字である文字列にのみ一致します。
^は文字列の先頭を表すと前述しましたが、別の意味もあります。 ^ が一連の角括弧内で使用される場合、それは「しない」または「除外する」を意味し、特定の文字を削除するためによく使用されます。前の例を使用すると、最初の文字を数字にすることはできません:
^[^0-9][0-9]$
このパターンは、「&5」、「g7」、および「-2」には一致しますが、「12」および「66」には一致しません。特定の文字を除外する例をいくつか示します:
[^a-z] //小文字を除くすべての文字
[^/^] //()(/)(^)を除くすべての文字
[^"'] //二重引用符 (") と一重引用符 (') を除くすべての文字
特殊文字「.」(ドット、ピリオド)は、正規表現で「改行」を除くすべての文字を表すために使用されます。したがって、パターン「^.5$」は、数字の 5 で終わり、「改行」以外の他の文字で始まる任意の 2 文字の文字列と一致します。パターン「.」は、空の文字列と「改行」のみを含む文字列を除く、任意の文字列と一致します。
PHP の正規表現にはいくつかの組み込みの共通文字クラスターがあり、リストは次のとおりです:
文字クラスターの意味
[[:alpha:]] 任意の文字
[[:digit:]] 任意の数字
[[:alnum:]] 任意の文字と数字
[[:space:]] 任意の白文字
[[:upper:]] 任意の大文字
[[: lower:]] 任意の小文字
[[:punct:]] 任意の句読点
[[:xdigit:]] [0-9a-fA-F] に相当する任意の 16 進数
7.3 再発の判定
ここまでで、文字または数字を一致させる方法はすでにわかりましたが、多くの場合、単語または数字のグループを一致させたい場合があります。単語は複数の文字で構成され、数字のグループは複数の単数で構成されます。文字または文字クラスターに続く中括弧 ({}) は、前のコンテンツが繰り返される回数を決定するために使用されます。
文字クラスターの意味
^[a-zA-Z_]$ すべての文字とアンダースコア
^[[:alpha:]]{3}$ すべての 3 文字の単語
^a$レターa
^a{4}$ aaaa
^a{2,4}$ aa,aaa or aaaa
^a{1,3}$ a,aa or aaa
^a{2,}$ 2 つ以上の a を含む文字列
^a{2,} 例: ツチブタと aaab、ただしリンゴではない
a{2,} 例: baad と aaa、ただしナンタケット島は除く
t{2} 2 つのタブ文字
.{2} 2 文字すべて
これらの例では、中括弧の 3 つの異なる使用法を説明します。数値 {x} は、「前の文字または文字クラスターが x 回のみ出現する」ことを意味し、数値とコンマ {x,} は、「前のコンテンツが x 回以上出現する」ことを意味します。 ,y} は、「前のコンテンツが少なくとも x 回表示されますが、y 回を超えない」ことを意味します。パターンをさらに多くの単語や数字に拡張できます:
^[a-zA-Z0-9_]{1,}$ //複数の文字、数字、またはアンダースコアを含むすべての文字列
^[0-9]{1,}$ //すべての正の数
^-{0,1}[0-9]{1,}$ //すべての整数
^-{0,1}[0-9]{0,}.{0,1}[0-9]{0,}$ //すべて 10 進数
最後の例は理解しにくいですよね。次のように見てください。オプションの負の符号 (-{0,1}) (^) で始まり、その後に 0 個以上の数字 ([0-) 9]{0,})、およびオプションの小数点 (.{0,1}) の後に 0 個以上の数字 ([0-9]{0,}) が続き、それ以外は何もありません ($ )。以下では、使用できるより簡単な方法について説明します。
特殊文字「?」は {0,1} に等しく、両方とも「0 または 1 つの前のコンテンツ」または「前のコンテンツはオプション」を表します。したがって、今の例は次のように簡略化できます:
^-?[0-9]{0,}.?[0-9]{0,}$
特殊文字「*」は {0,} に等しく、どちらも「0 個以上前のコンテンツ」を表します。最後に、文字「+」は {1,} に等しく、これは「1 つ以上の前のコンテンツ」を意味するため、上記の 4 つの例は次のように書くことができます:
^[a-zA-Z0-9_]+$ //複数の文字、数字、またはアンダースコアを含むすべての文字列
^[0-9]+$ //すべての正の数
^-?[0-9]+$ //すべての整数
^-?[0-9]*.?[0-9]*$ //すべて小数
もちろん、これによって技術的に正規表現の複雑さが軽減されるわけではありませんが、正規表現が読みやすくなります。