正規表現の概要と構文
なぜ正規表現を使用するのですか?
一般的な検索と置換の操作では、予想される検索結果と一致する正確なテキストを提供する必要があります。この手法は、静的テキストに対して単純な検索および置換タスクを実行するには十分かもしれませんが、柔軟性に欠けているため、この方法では動的テキストの検索が不可能ではないにしても困難になります。
正規表現を使用すると、次のことが可能になります。
1. 文字列内のパターンをテストします。
たとえば、入力文字列をテストして、文字列内に電話番号パターンまたはクレジット カード番号パターンが出現するかどうかを確認できます。これはデータ検証と呼ばれます。
2. テキストを置き換えます。
正規表現を使用すると、ドキュメント内の特定のテキストを識別したり、そのテキストを完全に削除したり、他のテキストに置き換えたりすることができます。
3. パターンマッチングに基づいて文字列から部分文字列を抽出します。
文書または入力フィールド内で特定のテキストを検索できます。
たとえば、サイト全体を検索し、古いコンテンツを削除し、特定の HTML 書式設定タグを置き換える必要がある場合があります。この場合、正規表現を使用して、このマテリアルまたはこの HTML 書式設定タグが各ファイルに存在するかどうかを判断できます。このプロセスにより、影響を受けるファイルのリストが、削除または変更が必要な内容を含むファイルに絞り込まれます。正規表現を使用して、古い内容を削除できます。最後に、正規表現を使用してタグを検索および置換できます。
正規表現 - 構文
正規表現 (正規表現) は、文字列に特定の部分文字列が含まれているかどうかを確認したり、一致する部分文字列を置き換えたり、特定の文字列から選択したりするために使用できる文字列一致パターンを記述します。条件など
ディレクトリをリストする場合、dir *.txt または ls *.txt 内の *.txt は正規表現ではありません。これは、ここでの * の意味が正規表現の * とは異なるためです。
正規表現の構築は、数式の作成と同じです。つまり、さまざまなメタ文字や演算子を使用して、小さな式を組み合わせて、より大きな式を作成できます。正規表現のコンポーネントは、単一の文字、文字のコレクション、文字の範囲、文字間の選択、またはこれらすべてのコンポーネントの任意の組み合わせにすることができます。
正規表現は、通常の文字 (文字 a ~ z など) と特殊文字 (「メタ文字」と呼ばれる) で構成されるテキスト パターンです。パターンは、テキストを検索するときに一致する 1 つ以上の文字列を記述します。正規表現は、文字パターンと検索文字列を照合するテンプレートとして機能します。
通常の文字
通常の文字には、メタキャラクターとして明示的に指定されていないすべての印刷可能文字と印刷不可能な文字が含まれます。これには、すべての大文字と小文字、すべての数字、すべての句読点、およびその他の記号が含まれます。
非印刷文字
非印刷文字も正規表現の一部にすることができます。次の表に、非印刷文字を表すエスケープ シーケンスを示します。
Character Description
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] に相当します。
タブ文字と一致しません。 x09 および cI に相当します。
v は垂直タブ文字と一致します。 x0b および cK に相当します。
特殊文字
いわゆる特殊文字は、上記の「*.txt」の * のように、単に任意の文字列の意味を意味する、特別な意味を持つ文字です。ファイル名に * が含まれるファイルを検索する場合は、* をエスケープする、つまり * の前に 1 を追加する必要があります。 ls *.txt。
多くのメタキャラクターは、それらを照合するときに特別な処理が必要です。これらの特殊文字と一致させるには、まず文字を「エスケープ」する必要があります。つまり、文字の前にバックスラッシュ文字 () を付けます。次の表に、正規表現の特殊文字を示します。
特殊文字 説明
$ 入力文字列の終了位置と一致します。 RegExp オブジェクトの Multiline プロパティが設定されている場合、$ は 'n' または 'r' にも一致します。 $ 文字そのものと一致させるには、$ を使用します。
( ) 部分式の開始と終了をマークします。部分式は後で使用するために取得できます。これらの文字と一致させるには、( と ) を使用します。
* 直前の部分式と 0 回以上一致します。 * 文字と一致させるには、* を使用します。
+ 前の部分式と 1 回以上一致します。 + 文字と一致させるには、+ を使用します。
。改行文字 n を除く任意の 1 文字と一致します。 . と一致させるには、 を使用します。
[ 角括弧式の始まりを示します。 [ と一致させるには、[ を使用します。
? 先行する部分式に 0 回または 1 回一致するか、非貪欲修飾子を指定します。 ? 文字に一致させるには、? を使用します。
次の文字を特殊文字、リテラル文字、後方参照、または 8 進エスケープ文字としてマークします。たとえば、「n」は文字「n」と一致します。 「n」は改行文字に一致します。シーケンス '\' は "" と一致し、'(' は "(" と一致します。
^ 角括弧式で使用されない限り、入力文字列の先頭と一致します。角括弧式で使用されている場合、文字セットが受け入れられないことを示します。 ^ 文字自体に一致するには、^ を使用します。{ に一致するには、{ を使用します。
修飾子正規表現の指定されたコンポーネントは、* または + または ? または {n} または {n,} または {n,m} の合計で 6 種類存在します。正規表現は次のとおりです: 文字
説明* 前の部分式と 0 回以上一致します。たとえば、zo* は "z" および ".zoo" と一致します。* は {0, と同等です。 }. + 前の部分式と 1 回以上一致します。たとえば、「zo+」は「zo」と一致しますが、「z」は一致しません。たとえば、前の部分式は 0 回または 1 回、{0,1} の "do" または "does" と一致します。整数。たとえば、「o{2}」は「Bob」の「o」と一致しますが、「food」の 2 つの「o」は一致します。
{n,} n は負ではない整数です。少なくとも n 回一致します。たとえば、「o{2,}」は「Bob」の「o」とは一致しませんが、「foooood」のすべての「o」と一致します。 「o{1,}」は「o+」と同等です。 「o{0,}」は「o*」と同等です。
{n,m} m と n は両方とも非負の整数であり、n <= m です。少なくとも n 回、最大で m 回一致します。たとえば、「o{1,3}」は「fooooood」の最初の 3 つの o と一致します。 「o{0,1}」は「o?」と同等です。カンマと 2 つの数字の間にスペースを入れることはできないことに注意してください。
大きな入力ドキュメントでは章番号が 9 を超える可能性があるため、2 桁または 3 桁の章番号を処理する方法が必要です。修飾子はこの能力を与えます。次の正規表現は、任意の桁数で番号付けされた章タイトルに一致します:
/Chapter [1-9][0-9]*/
範囲式の後に修飾子が表示されることに注意してください。したがって、これは範囲式全体に適用されます。この場合、0 ~ 9 (両端の値を含む) の数値のみが指定されます。
2 番目以降の位置に必ずしも数字を入れる必要がないため、ここでは + 修飾子は使用されません。それも使わないの?章番号が 2 桁に制限されているためです。章の後に少なくとも 1 つの数字とスペース文字が一致する必要があります。
章番号が 99 章のみに制限されていることがわかっている場合は、以下の式を使用して少なくとも 1 桁、最大 2 桁を指定できます。
/Chapter [0-9]{1,2}/
上記の式の欠点は、99 より大きい章番号が最初の 2 桁にしか一致しないことです。もう一つの欠点は、Chapter 0 も一致することです。 2 桁のみを照合するより適切な表現は次のようになります:
/Chapter [1-9][0-9]?/
または
/Chapter [1-9][0-9] The { 0,1}/
*、+、および ? 修飾子は、後ろに ? を追加することで可能な限り多くのリテラルと一致するため、すべて貪欲です。
たとえば、HTML ドキュメント内で H1 タグで囲まれた章のタイトルを検索するとします。文書内のテキストは次のようになります:
<H1>第 1 章 – 正規表現の概要</H1>
次の式は、開始の不等号 (<) から終了 H1 タグまで一致します。より大きい記号 (>)。
/<.*>/
開始 H1 タグのみを一致させる必要がある場合、以下の「非貪欲」式は <H1> のみに一致します。
/<.*?>/
*、+、または ? 修飾子の後に ? を置くと、式は「貪欲な」式から「非貪欲な」式または最小一致に変換されます。
ロケーター
ロケーターを使用すると、正規表現を行の先頭または末尾に固定できます。また、単語内、単語の先頭、または単語の末尾に表示される正規表現を作成することもできます。
ロケーターは文字列または単語の境界を表すために使用され、^ と $ はそれぞれ文字列の先頭と末尾を指し、b は単語の前または後ろの境界を表し、B は単語以外の境界を表します。 。
正規表現の修飾子は次のとおりです:
Character Description
^ 入力文字列の先頭と一致します。 RegExp オブジェクトの Multiline プロパティが設定されている場合、^ は n または r の後の位置にも一致します。
$ 入力文字列の末尾と一致します。 RegExp オブジェクトの Multiline プロパティが設定されている場合、$ は n または r の前の位置にも一致します。
b 単語の境界、つまり単語とスペースの間の位置に一致します。
B 非単語境界のマッチング。
注: アンカー ポイントを含む修飾子は使用できません。改行または単語境界の直前または直後に複数の位置を置くことはできないため、^* などの表現は許可されません。
テキスト行の先頭のテキストを照合するには、正規表現の先頭に ^ 文字を使用します。この ^ の使用と括弧内の式の使用を混同しないでください。
テキスト行の末尾のテキストと一致するには、正規表現の末尾に $ 文字を使用します。
章のタイトルを検索するときにアンカー ポイントを使用するには、次の正規表現は、末尾に 2 桁のみを含み、行の先頭に表示される章のタイトルと一致します:
/^Chapter [1-9][ 0-9 ]{0,1}/
実際の章のタイトルは行の先頭に表示されるだけでなく、行内の唯一のテキストでもあります。これは、行の先頭と同じ行の末尾の両方に表示されます。次の式は、指定された一致が相互参照ではなく章のみに一致することを保証します。これを行うには、テキスト行の先頭と末尾のみに一致する正規表現を作成します。
/^Chapter [1-9][0-9]{0,1}$/
は、単語の境界を若干異なる方法で照合しますが、正規表現に重要な機能を追加します。単語の境界は、単語とスペースの間の位置です。非単語境界は、その他の位置です。次の式は、Chapter という単語の最初の 3 文字と一致します。これらの 3 文字は単語境界の後に出現するためです:
/bCha/
b 文字の位置は非常に重要です。単語の先頭が一致する文字列の先頭にある場合は、その単語の先頭で一致するものを探します。それが文字列の末尾にある場合は、単語の末尾で一致するものを探します。たとえば、次の式は、単語 Chapter の文字列 ter と一致します。これは単語境界の前にあるためです。
/terb/
次の式は、Chapter の文字列 apt と一致しますが、apt の aptitude 文字列とは一致しません。
/バプト/
文字列 apt は、単語 Chapter では単語以外の境界で発生しますが、単語 aptitude では単語境界で発生します。 B 非単語境界演算子の場合、単語の先頭か末尾が一致するかどうかは関係ないため、位置は重要ではありません。
Select
すべての選択をかっこで囲み、隣接する選択を | で区切ります。ただし、括弧を使用すると、関連する一致がキャッシュされるという副作用が生じます。この場合、最初のオプションの前に ?: を使用すると、この副作用を排除できます。
このうち、?: は非キャプチャー要素の 1 つで、他の 2 つの非キャプチャー要素は ?= と ?! です。これら 2 つは前方参照であり、括弧内にあるものと一致します。後者は、正規表現パターンに一致しない任意の位置の検索文字列に一致します。
後方参照
正規表現パターンまたはパターンの一部をかっこで囲むと、関連付けられた一致が一時バッファーに保存され、キャプチャされた各部分一致が正規表現パターンと同様にキャプチャされます。外観は左から右へ。バッファの番号付けは 1 から始まり、最大 99 個のキャプチャされた部分式を保存できます。各バッファーには、「n」を使用してアクセスできます。n は、特定のバッファーを識別する 1 桁または 2 桁の 10 進数です。
キャプチャは、関連付けられた一致の保存を無視して、非キャプチャ メタキャラクタ「?:」、「?=」、または「?!」を使用してオーバーライドできます。
後方参照の最もシンプルで便利なアプリケーションの 1 つは、テキスト内で隣接する 2 つの同一の単語の一致を見つける機能です。次の文を例に挙げます:
ガソリンのコストは上がりますか?
上の文には明らかに複数の単語が繰り返されています。各単語の繰り返しを探すことなく、この文を見つける方法を工夫するとよいでしょう。次の正規表現は、単一の部分式を使用してこれを実現します。
/b([a-z]+) 1b/gi
は、[a-z]+ で指定された、1 つ以上の文字を含む式をキャプチャします。正規表現の 2 番目の部分は、以前に取得された部分一致への参照、つまり、括弧表現と完全に一致する単語の 2 番目の出現です。 1 は最初のサブマッチを指定します。単語境界メタキャラクターにより、単語全体のみが確実に検出されます。そうしないと、「発行されました」や「これは」などの語句がこの式で正しく認識されません。
正規表現の後のグローバル タグ (g) は、入力文字列内で見つかったすべての一致にその式が適用されることを示します。式の末尾にある case-insensitive (i) タグは、大文字と小文字を区別しないことを指定します。複数行タグは、改行文字のどちらかの側で発生する可能性のある一致を指定します。
後方参照は、Universal Resource Indicator (URI) をそのコンポーネントに分割することもできます。次の URI をプロトコル (ftp、http など)、ドメイン アドレス、およびページ/パスに分割するとします:
http://www.w3cschool.cc:80/html/html-tutorial.html
以下の正規表現はこの機能を提供します:
/(w+)://([^/:]+)(:d*)?([^# ]*)/
最初の括弧部分式は、Web アドレスのプロトコル部分をキャプチャします。この部分式は、コロンと 2 つのスラッシュが前にある任意の単語と一致します。 2 番目の括弧部分式は、アドレスのドメイン アドレス部分を取得します。部分式は、/ と : を除く 1 つ以上の文字と一致します。 3 番目の括弧内の部分式は、ポート番号 (指定されている場合) を取得します。この部分式は、コロンに続く 0 個以上の数字と一致します。この部分式は 1 回だけ繰り返すことができます。最後に、括弧で囲まれた 4 番目の部分式は、Web アドレスで指定されたパスおよび/またはページ情報を取得します。この部分式は、# またはスペース文字を含まない任意の文字シーケンスと一致します。
上記の URI に正規表現を適用すると、各部分一致には以下が含まれます:
1) 最初の括弧で囲まれた部分式には「http」が含まれます
2) 2 番目の括弧で囲まれた部分式には「www .w3cschool.cc」が含まれます
3) 3 番目の括弧の部分表現には「:80」が含まれています
4) 4 番目の括弧の部分表現には「../html/html-tutorial.html」が含まれています
atom
アトムは、正規表現の最小単位です。アトムは一致する必要があるコンテンツです。有効な正規表現には、少なくとも 1 つのアトムが含まれている必要があります。
説明: 私たちが目にするスペース、復帰、改行、0 ~ 9、A-Za-Z、中国語、句読点、特殊記号はすべてアトムです。
アトミックな例を行う前に、まず関数 preg_match:
int preg_match (string $ Regular, string $string[, array &$result]) について説明しましょう
関数: $regulator 変数 $string に従って照合します変数。存在する場合は、一致の数を返し、一致した結果を $result 変数に入れます。結果が見つからない場合は 0 が返されます。
開始と終了
^は開始を意味し、$は終了を意味します
次のコードはdateで始まる任意の数値と一致します
$str = 'date20150121';
echo '一致成功';
} else {
echo '一致失敗';
}
w は、文字、数字、またはアンダースコア文字の一致に使用されます。
d は、 を表す数値 (D は非数値を意味します) と一致します
$str = 'date20150121';
if (preg_match('/^w/', $str, $matches)) {
print_r($matches);
} else {
echo 'Match failed';
}
特別に識別された原子
Atom 説明
d 0-9 と一致します
D 0-9 を除くすべての文字
w a-zA-Z0-9_
W 0-9A-Za-z を除くすべての文字_
s スペースのすべての空白文字と一致します
S 空白以外のすべての文字と一致します
[ ] アトムの範囲を指定します
例:
d は 0 ~ 9 に一致します
<?php
$zz = '/\d/';
$string = '我爱喝9你爱不爱喝';
if(preg_match($zz, $string, $matches)){
echo '匹配到了,结果为:';
var_dump($matches);
}else{
echo '没有匹配到';
}
?>
D は 0-9 以外の値と一致します
<?php $zz = '/\D/'; $string = '121243中23453453'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,结果为:'; var_dump($matches); }else{ echo '没有匹配到'; } ?>照合は成功し、試合に入ります。 0 ~ 9 の文字ではないためです。
w は a-zA-Z0-9_
<?php $zz = '/\w/'; $string = '新中_国万岁呀万岁'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,结果为:'; var_dump($matches); }else{ echo '没有匹配到'; } ?>と一致します 一致は成功し、アンダースコアが一致します。
W は非 a-zA-Z0-9_
<?php $zz = '/\w/'; $string = 'afasABCWEQR44231284737'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,结果为:'; var_dump($matches); }else{ echo '没有匹配到'; } ?>と一致しましたが失敗しました。なぜなら、上記はすべて a-zA-Z0-9_ であり、a-zA-Z0-9_ でないものは何もないからです。
s は、スペース以外のすべての空白文字と一致します。
<?php $zz = '/\s/'; $string = "中国万 岁"; if(preg_match($zz, $string, $matches)){ echo '匹配到了,结果为:'; var_dump($matches); }else{ echo '没有匹配到'; } ?>復帰があるため、一致は成功します。
S の空でない文字
<?php $zz = '/\s/'; $string = " a "; if(preg_match($zz, $string, $matches)){ echo '匹配到了,结果为:'; var_dump($matches); }else{ echo '没有匹配到'; } ?>が正常に一致しました。スペースはありますが、改行とインデントが表示されます。ただし、空白以外の文字 a が存在します。したがって、試合は成功です。
[] は原子の範囲を指定します
<?php $zz = '/[0-5]\w+/'; $string = '6a'; $string1 = '1C'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,结果为:'; var_dump($matches); }else{ echo '没有匹配到'; } ?>結論: 上記の例では、0-5 は $string と一致しませんでしたが、$string1 は成功しました。 $string の最初の値は 6 であり、[0-5] の範囲内にないためです。
<?php $zz = '/[a-zA-Z0-9_]\w/'; $string = 'ab'; $string1 = '9A'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,结果为:'; var_dump($matches); }else{ echo '没有匹配到'; } ?>
結論:
<?php $zz = '/[abc]\d+/'; $string = 'a9'; $string1 = 'b1'; $string2 = 'c5'; $string3 = 'd4'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,结果为:'; var_dump($matches); }else{ echo '没有匹配到'; } ?>結論:$string、$string1、$string2 は正常に一致しますが、$string3 は一致しません。 $string3は[abc]の範囲を超えているため、dから始まります。
[^ 文字] は指定された範囲の文字と一致しません
<?php $zz = '/[^0-9A-Za-z_]/'; $string = 'aaaaab311dd'; $string1 = '!$@!#%$#^##'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,结果为:'; var_dump($matches); }else{ echo '没有匹配到'; } ?>結論:
1) $string のマッチングは失敗しましたが、$string1 のマッチングは成功しました。角括弧内にサーカムフレックス文字があるためです。
2) 角括弧内の ^ サーカムフレックス文字の機能は、角括弧内の文字と一致することではありません。