この記事では、パターン修飾子、貪欲マッチングと非貪欲マッチング、Unicode モード、ルックアラウンドなどの正規表現の知識ポイントを HTML 要素を抽出して紹介します。
この記事を読む前に、同じシリーズの記事「PHP 実践正規表現 (1): 携帯電話番号の認証」をよく読んでおくことをお勧めします。
基本抽出
こんなフォームもあります
ユーザー名 | 職業 |
コービー・ブライアント | バスケットボール選手 |
ジェイ・チョウ | シンガー、ソングライター、プロデューサー、俳優、監督 |
Lionel Messi | フットボール選手 |
そのソースコードは次のとおりです:
<table> <thead> <tr><th>用户名</th><th>职业</th></tr> </thead> <tbody> <tr> <td>Kobe Bryant</td><td>篮球运动员</td> </tr> <tr> <td>Jay Chou</td><td>歌手、词曲创作人、制作人、演员、导演</td> </tr> <tr> <td>Lionel Messi</td><td>足球运动员</td> </tr> </tbody></table>
ログイン後にコピー
次に、
の最初の 要素を抽出する必要があります。最も単純な正規表現は次のようになります:
s+.*
ここで、
s は実際の PHP 正規表現です (1): 携帯電話番号を確認する導入された文字グループの略語の 1 つで、復帰、スペース、タブ、その他の空白文字を表します
数量子 + は、修飾される文字または文字グループの出現数が 1 以上であることを意味します
ドット文字 は、「任意の文字」に一致する正規表現の特別なメタ文字です
終了タグ 内のスラッシュ / は、PHP 正規表現文字のパターン区切り文字であるため、スラッシュ文字を表すためにエスケープする必要があります。
しかし、実際には、そのような式は上記の
から最初の 要素を抽出できません ここでの主な問題は、デフォルトでは改行文字 n と一致しないことです。この問題を解決するには 2 つの方法があります:
-
パターン修飾子 s を使用します。正規表現は /
s+.*
/s または (?s) です。 ;s+
.*
。パターン修飾子 s の機能は、ドット文字を改行文字と一致させることです。 -
すべての文字と一致するには、ピリオド文字を [sS] または [wW] または [dD] に置き換えます。正規表現は
s+[sS]*
です Pattern Modifiers (パターン修飾子) について、ここで詳しく紹介する必要があります (PHP でサポートされているすべてのパターン修飾子を表示するには、ここをクリックしてください)。パターン修飾子は、正規表現のデフォルト ルールの一部を変更できます。一般的に使用されるパターン修飾子には、i、s、U、u などが含まれます。これらの一部については、ここでは説明しません。使用する場合は後ほど詳しく紹介します。ここでは主に、2 つの式メソッド /.../{modifier} と...(?{modifier}).... の違いを比較します。
モード修飾子 | /.../{修飾子} | ...(?{修飾子})... |
例 | /
.*
/ s | (?s).*
| 名前 (PHP マニュアル) パターン修飾子 | パターン内修飾子 | |
名前 (「通常のガイドライン」) 事前定義された定数 | パターン修飾子 | |
スコープ 正規表現全体 | グループ(部分式)内にない場合、グループ(部分式)内にある場合は、それに続くすべての正規表現に影響します。 ) 式)、グループ化の残りの部分に影響します。グループ化がなく、正規表現全体の先頭に配置される場合、/.../{modifier} と同等になります。 | その他のプログラミング言語 |
はサポートされていない場合があります 通常サポートされています | |
上の gif からわかるように、抽出結果には 1 つだけではなく 3 つの tr が含まれています。これは、正規表現の量指定子がデフォルトで 貪欲な一致 に設定されているためです。ここで、.* は最後に文字がなくなるまですべての文字に一致し、その後、
の最後の に戻ります。正規表現内の と一致して、一致プロセス全体が完了します。最終結果には 3 つの が含まれます。 パターン修飾子 U を使用して正規表現全体を非貪欲モードとして指定することも、非貪欲一致量指定子を使用して特定の量指定子を非貪欲モードとして指定することもできます:
-
正規表現全体を非貪欲モードとして指定します:
/
s+.*
/Us または (?Us)
s +.*
非貪欲量指定子:
/
s+.*?
/s 完全な貪欲数量子 (優先順位数量子と一致) と非貪欲数量子 (優先順位数量子を無視) を次の表に示します。
*
*? | 出現する場合もあれば、出現しない場合もあり、出現回数に上限はありません | | +
+? | 最低1回、上限なし | | ?
?? | 発生回数0回または1回 | | {m,n}
{m,n}? | 発生回数ですm 以上、n 以下 | | {m,}
{m,}? | は少なくとも m 回出現し、上限なし | | {0,n}
{0,n}? | は 0 回 -n 回出現します | | 指定されたコンテンツを含む行を抽出します
テーブルから アスリート | に関するすべてのレコードを抽出したいと仮定すると、/
を使用できます。* Athletes.*
この式は Unicode エンコード環境の結果と一致しますが、GBK 環境では必ずしも一致するとは限りません。モード修飾子 u を使用して Unicode モードを指定できます: | /.*athlete.*
/us
Unicode モードでは、code value
を使用して中国語の文字を置き換えることもできます: /.*x{8fd0}x{52a8}x{5458}.*
/us
x{hex} の形式は、Unicode のコード値を表すために php 通常で使用されますコード値を使用する利点は、文字グループと組み合わせて範囲を表すことができることです。たとえば、[x{4e00}-x{9fff}] はすべての中国語の文字と一致することを意味します。
上記の式は結果と一致しますが、正しくありません。最初の から最後の
までの文字列全体と一致していることがわかります。 直観的には、正規表現で最初に「athlete」と一致し、次に左側で最も近い
を探し、右側で最も近い
を探します。しかし、実際には、正規表現は左から右に、つまり から開始して一致します。正規表現全体の一致を次の表に示します (空白文字は示されていません)。 式
一致値
/
|
|
---|
| .* |
ユーザー名 |
;プロ |
コービー・ブライアント | バスケットボール
|
| アスリート | させてください
| .* |
ジェイ・チョウ | シンガー、ソングライター、プロデューサー、俳優、監督 |
リオネル・メッシ | サッカー選手 | |
| /私たち |
ここでは、両方の .* が予想よりも多くの文字に一致します。 .* が予想よりも多くの文字に一致する 2 番目の理由は、正規表現がデフォルトで貪欲一致パターンに設定されており、文字列の最後まで残りの文字列のすべての文字に一致し、その後最後の < /tr> に戻るためです。この問題は、貪欲でない一致モードを指定することで解決できます。ただし、正規表現は左から右に一致し、式内の |
は文字列内の最初の
に一致するため、最初の .* が予想より多くの文字に一致するのは正常です。 * は、文字列の末尾までの残りのすべての文字と一致し、その後「athlete」に戻ります。 まず、非貪欲マッチングを使用した場合の結果を見てみましょう:
2 番目の .* マッチング文字がすでに必要なものであることがわかります。では、最初の .* が予想よりも多くの文字に一致するという問題を解決するにはどうすればよいでしょうか?
これまでの記事で紹介した知識だけを使えば解決する方法はあります。まず、PHP の preg_match_all 関数を非貪欲一致モードと組み合わせて使用することにより、左から右 (
...
) までのすべての行を照合し、各行をスキャンしてフィルタリングします。 「アスリート」を含む行で十分です。 もちろん、純粋な正規表現を使用してこの問題を解決することもできます。正規表現の使用にある程度の経験がある友人なら、同じ位置に出現する可能性のある文字を表す 除外文字グループ[...] を簡単に思いつくかもしれません。 除外文字グループ は、同じ位置に出現できない文字を表します。その形式は [^...] であり、除外文字グループは左角かっこ [ の直後にある ^ で表されます。たとえば、[^d] は、一致する文字が数字以外の任意の文字であることを意味します。 (^)* のような除外される部分式がある場合、
を除外するには最初の .* を指定するだけです。ただし、残念ながら、正規表現には除外される部分式や除外されるグループはありません。この場合、 look-around のみを使用できます。 ) はどの文字にも一致せず、「その場で停止して周囲を見回す」ために使用されます。上記の式は負の逐次ルックアラウンド
を使用しており、その形式は (?!...) です。具体的には、 (.(?!
))* の場合、 . が文字に一致する場合は常に、現在の一致する文字の右側に
が表示されない場合、一致は成功します。 完全な参照には以下が含まれます:
名前
表記 意味
特定の順序で見てください (?=...) | 右に見て、 look around は右側に表示されます Match | |
Negative look-around (?!...) | look around の内容が右側に表示されない場合のみ、右側に目を向けます | |
必ず逆の順序で見てください (?<=... ) | 左に見てください。左にある内容が左側に表示されている場合のみ、一致します | |
逆の順序で周りを否定的に見てください (? | ルックアラウンドの内容が左側に表示されない場合のみ、左を見てください | |
上記の正規表現はグループ(部分式)を持っているので、一致する結果には添字 0 だけでなく添字 1 も含まれます。ここでの添字 1 の結果は実際には役に立ちません。前に紹介した 非キャプチャ グループ化 を使用できます: | / |
(?:.() ?!
))*athletes.*
/Us 実際の目的は、「Athlete」行を含むすべての項目を抽出することであり、上記では最初の項目のみが抽出されるため、preg_match 関数は次のことを行う必要があります。 preg_match_all に置き換えられます。 |
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
-
2024-10-22 09:46:29
-
2024-10-13 13:53:41
-
2024-10-12 12:15:51
-
2024-10-11 22:47:31
-
2024-10-11 19:36:51
-
2024-10-11 15:50:41
-
2024-10-11 15:07:41
-
2024-10-11 14:21:21
-
2024-10-11 12:59:11
-
2024-10-11 12:17:31