ホームページ  >  記事  >  バックエンド開発  >  PHPインタビューにおける正規表現の知識まとめ(超詳細)

PHPインタビューにおける正規表現の知識まとめ(超詳細)

不言
不言転載
2019-01-09 10:25:456593ブラウズ

この記事は、PHP 面接での正規表現に関する知識をまとめた (超詳細な) ものです。一定の参考価値があります。困っている友人は参考にしてください。お役に立てれば幸いです。

関連おすすめ: 「2019 PHP 面接質問まとめ (集)

1. はじめに

#1. 正規表現とは

正規表現 (正規表現) は、特定のパターンを使用して文字列の種類と一致する式です。

正規表現は、単一の文字列を使用して、特定の構文規則に一致する一連の文字列を記述および照合します。
正規表現は面倒ですが強力です。学習後、適用すると効率が向上するだけでなく、絶対的な達成感を得ることができます。このチュートリアルを注意深く読み、適用する際に特定の参照を作成する限り、正規表現を習得するのは問題ありません。
多くのプログラミング言語は、正規表現を使用した文字列操作をサポートしています。

2. 正規表現の役割

文字列の分割、検索、一致、置換

3. PHP 式の正規表現

PHP には 2 つの正規表現関数ライブラリのセットがあります。2 つの関数は似ていますが、実行効率がわずかに異なります。

1 つのセットは PCRE ( Perl 互換の正規表現 ) ライブラリによって提供されます。プレフィックス「preg_」の付いた名前の関数;

POSIX (Unix のポータブル オペレーティング システム インターフェイス) 拡張機能によって提供されるセット。プレフィックス「ereg_」が付いた名前の関数を使用してください。

PCRE は Perl 言語に由来しており、Perl は文字列操作に最も強力な言語の 1 つです。PHP の初期バージョンは Perl によって開発された製品でした。

PCRE 構文は、POSIX 構文よりも多くの機能をサポートし、強力です。したがって、この記事では、
PCRE 構文

4 の正規表現を中心に紹介します。 正規表現の構成

PHP では、正規表現を分割します。区切り文字、式、パターン修飾子の 3 つの部分に分かれています。

区切り文字

区切り文字には、文字、数字、バックスラッシュ (\)、空白文字を除く任意の ASCII 文字を使用できます。

最も一般的に使用される区切り文字は、スラッシュ (/)、ハッシュ記号 (#)、および否定記号 (~) です。

は、いくつかの特殊文字と特殊でない文字列で構成されています。正規表現の一致ルールを決定する主要な部分です。

モード修飾子

は、特定の機能/モードをオンまたはオフにするために使用されます。

2. デリミタ

1. デリミタの選択

PCRE 関数を使用する場合、正規表現を囲む必要があります区切り文字によって。

区切り文字には、文字、数字、バックスラッシュ (
\)、および空白文字を除く任意の ASCII 文字を使用できます。
最も一般的に使用される区切り文字は、スラッシュ (/)、ハッシュ記号 (#)、および否定記号 (~) です。

/foo bar/ (合法)
#^[^0-9]$# (合法)
+php+    (合法)
%[a-zA-Z0-9_-]%    (合法)
#[a-zA-Z0-9_-]/    (非法,两边的分隔符不同)
a[a-zA-Z0-9_-]a    (非法,分隔符不能是字母)
\[a-zA-Z0-9_-]\    (非法,分隔符不能是反斜线(`\`))

上記の区切り文字に加えて、括弧スタイルの区切り文字も使用できます。左括弧と右括弧は、それぞれ開始区切り文字と終了区切り文字として機能します。

{this is a pattern}
2. 区切り文字の使用

正規表現で区切り文字を使用する場合は、バックスラッシュ (\) エスケープを使用する必要があります。 正規表現内で区切り文字が頻繁に使用される場合は、読みやすさを向上させるために他の区切り文字を使用することをお勧めします。

/http:\/\//
#http://#

文字列を正規表現に入れる必要がある場合は、preg_quote() 関数を使用して文字列をエスケープできます。 2 番目のパラメータ (オプション) を使用して、エスケープする必要がある区切り文字を指定できます。

//在这个例子中,preg_quote($word) 用于保持星号和正斜杠(/)原文涵义,使其不使用正则表达式中的特殊语义。
$textBody = "This book is */very/* difficult to find.";
$word = "*/very/*";
$reg = "/" . preg_quote($word, '/') . "/";

echo $reg; // 输出 '/\*\/very\/\*/'

echo preg_replace ($reg, "<i>" . $word . "</i>", $textBody); // 输出 'This book is <i>*/very/*</i> difficult to find.'

終了区切り文字の後にパターン修飾子を追加して、マッチング効果に影響を与えることができます。

次の例は、大文字と小文字を区別しない一致です

#[a-z]#i

3. メタ文字

1. エスケープ文字

#文字##\次の文字を変更します 特殊文字でマークされています、リテラル文字、または後方参照。 2. ロケーター
説明
たとえば、「n」は文字「n」と一致します。 「n」は改行文字に一致します。シーケンス '\' は "" に一致し、"(" は "(" に一致します。

CharacterDescription$\b\B

3. 修飾子

# 入力文字列の先頭 (または複数の文字列の先頭) と一致します。 -line モード、これは行の先頭です)
は入力文字列 (または複数行) の末尾と一致しますモード、行末です )
単語の境界、つまり単語と単語の間の位置と一致します。スペース
非単語境界のマッチング
前の部分式と 0 回以上一致します。 前述の部分式と 1 回以上一致します。 この文字が量指定子として使用される場合、前の部分式と 0 回または 1 回一致することを意味します。 n は負ではない整数です。特定の回数 n 回一致します。 n は負ではない整数です。少なくとも n 回一致します。 m と n は両方とも非負の整数であり、n たとえば、「o{1,3}」は「fooooood」の最初の 3 つの o と一致します。 「o{0,1}」は「o?」と同等です。カンマと 2 つの数字の間にスペースを入れることはできないことに注意してください。
文字 説明
# # * たとえば、zo
は「z」と「zoo」に一致します。 {0,} と同等。
たとえば、「zo 」は「zo」と「zoo」に一致しますが、「z」には一致しません。 {1,} と同等。
? たとえば、 "do(es)?" は "do" または "does" と一致します。 ? {0,1} に相当します。
{n} たとえば、「o{2}」は「Bob」の「o」と一致することはできませんが、「food」の 2 つの o とは一致します。
{n,} たとえば、「o{2,}」は「Bob」の「o」とは一致しませんが、「foooood」のすべての「o」には一致します。 「o{1,}」は「o 」と同等です。 「o{0,}」は「o*」と同等です。
{n,m}
4. 一般的な文字

文字説明 数字と一致します。 数字以外の文字と一致します。 文字、数字、アンダースコアと一致します。 文字、数字、アンダースコア以外の文字に一致します。 スペース、タブ、フォーム フィードなどを含む任意の空白文字と一致します。 #\S[^ \f\n\r\t\v].「n」を含む任意の文字と一致するには、「(.5. 非印刷文字

\d [0-9]と同等。
\D [^0-9]と同等。
\w [A-Za-z0-9_]と同等。
\W [^A-Za-z0-9_]と同等。
\s [ \f\n\r\t\v] と同等。
空白以外の任意の文字と一致します。 と同等。
改行 (n、r) を除く任意の 1 文字と一致します。
n)」のような正規表現を使用します。

文字\n\r\t6. 複数選択分岐文字
説明
改行文字と一致します。 x0a および cJ に相当します。
復帰文字と一致します。 x0d および cM に相当します。
タブ文字と一致します。 x09 および cI に相当します。

文字|たとえば、「z|food」は「z」または「food」と一致します。 '(z|f|g)ood' は、「zood」、「food」、または「good」に一致します。 #7. キャラクターグループ
説明
縦棒文字| は複数の選択に一致します。

キャラクター説明[x|y] x または y と一致します。 [xyz][abc][^xyz][^abc][a-z][a-z][^a-z][^a-z]

8. 貪欲でない一致文字

たとえば、「z|food」は「z」または「food」と一致します。 '(z|f)ood' は、「zood」または「food」と一致します。
文字セット。含まれている文字のいずれかと一致します。 たとえば、 は「plain」の「a」に一致します。
負の値の文字セット。含まれていない任意の文字と一致します。 たとえば、 は、「plain」の 'p'、'l'、'i'、'n' に一致します。
文字範囲。指定された範囲内の任意の文字と一致します。 たとえば、 は、「a」から「z」の範囲内の任意の小文字の英字と一致します。
負の文字範囲。指定された範囲内にない任意の文字と一致します。 たとえば、 は、「a」から「z」の範囲にない任意の文字に一致します。
文字 説明
##? 文字が他のリミッター (*, , ?, {n}, {n,}, {n,m}) の直後にある場合のパターンと一致します。 。
非貪欲モードは、検索文字列の可能な限り少ない部分と一致しますが、デフォルトの貪欲モードは、検索文字列の可能な限り多くの部分と一致します。
たとえば、文字列「oooo」の場合、「o ?」は 1 つの「o」に一致し、「o 」はすべての「o」に一致します。

9. ( )グループ

リバース (後方確認) ポジティブ事前チェックは、順方向ポジティブ事前チェックと似ていますが、次の点が異なります。反対方向。 ##(?リバース ネガティブ プリチェックはフォワード ネガティブ プリチェックと似ていますが、方向が逆です。 たとえば、「(?

四、模式修饰符

1. i(不区分大小写)

如果设置了这个修饰符,正则表达式中的字母会进行大小写不敏感匹配。

2. m(多行模式)

默认情况下,PCRE 认为目标字符串是由单行字符组成的(然而实际上它可能会包含多行)。
"行首"元字符 (^) 仅匹配字符串的开始位置, 而"行末"元字符 ($) 仅匹配字符串末尾, 或者最后的换行符(除非设置了 D 修饰符)。

当这个修饰符设置之后,“行首”元字符 (^) 和“行末”元字符 ($) 就会匹配目标字符串中任意换行符之前或之后,另外,还分别匹配目标字符串的最开始和最末尾位置。

如果目标字符串 中没有 "n" 字符,或者正则表达式中没有出现 ^$,设置这个修饰符不产生任何影响。

3. s(点号通配模式)

默认情况下,点号(.)不匹配换行符。
如果设置了这个修饰符,正则表达式中的点号元字符匹配所有字符,包含换行符。

4. U(贪婪模式)

这个修饰符与前面提到的 ? 作用相同,使正则表达式默认为非贪婪匹配,通过量词后紧跟 ? 的方式可以使其转为贪婪匹配。

在非贪婪模式,通常不能匹配超过 pcre.backtrack_limit 的字符。

贪婪模式

$str = &#39;<b>abc</b><b>def</b>';
$pattern = '/<b>.*</b>/';
preg_replace($pattern, '\\1', $str);<p><code>.*</code>会匹配 <code>abc</b><b>def</code></p>
<h4><strong>非贪婪模式</strong></h4>
<p><strong>方法一、使用 <code>?</code> 转为非贪婪模式</strong></p>
<pre class="brush:php;toolbar:false">$str = '<b>abc</b><b>def</b>';
$pattern = '/<b>.*?</b>/';
preg_replace($pattern, '\\1', $str);

.*会分别匹配 abcdef

方法二、使用修饰符 U 转为非贪婪模式

$str = '<b>abc</b><b>def</b>';
$pattern = '/<b>.*</b>/U';
preg_replace($pattern, '\\1', $str);

5. u(支持UTF-8转义表达)

此修正符使正则表达式和目标字符串都被认为是 utf-8 编码。
无效的目标字符串会导致 preg_* 函数什么都匹配不到;无效的正则表达式字符串会导致 E_WARNING 级别的错误。

$str = '中文';

$pattern = '/^[\x{4e00}-\x{9fa5}]+$/u';

if (preg_match($pattern, $str)) {
    echo '该字符串全是中文';
} else {
    echo '该字符串不全是中文';
}

6. D(结尾限制)

默认情况下,如果使用 $ 限制结尾字符,当字符串以一个换行符结尾时, $符号还会匹配该换行符(但不会匹配之前的任何换行符)。
如果设置这个修饰符,正则表达式中的 $ 符号仅匹配目标字符串的末尾。
如果设置了修饰符 m,这个修饰符被忽略。

7. x

如果设置了这个修饰符,正则表达式中的没有经过转义的或不在字符类中的空白数据字符总会被忽略, 并且位于一个未转义的字符类外部的#字符和下一个换行符之间的字符也被忽略。

8. A

如果设置了这个修饰符,正则表达式被强制为"锚定"模式,也就是说约束匹配使其仅从 目标字符串的开始位置搜索。

9. S

当一个正则表达式需要多次使用的时候,为了得到匹配速度的提升,值得花费一些时间对其进行一些额外的分析。
如果设置了这个修饰符,这个额外的分析就会执行。
当前,这种对一个正则表达式的分析仅仅适用于非锚定模式的匹配(即没有单独的固定开始字符)。

五、反向引用

使用 ( ) 标记的开始和结束的多个原子,不仅是一个独立的单元,也是一个子表达式。
在一个 ( ) 中的子表达式外面,反斜线紧跟一个大于 0 的数字,就是对之前出现的某个子表达式的后向引用。
后向引用用于重复搜索前面某个  ( ) 中的子表达式匹配的文本。

1. 在正则表达式中使用反向引用

(sens|respons)e and \1ibility 将会匹配 ”sense and sensibility” 和 ”response and responsibility”, 而不会匹配 ”sense and responsibility”

2. 在PCRE函数中使用反向引用

<?php
$str = '<b>abc</b><b>def</b>';
$pattern = '/<b>(.*)<\/b><b>(.*)<\/b>/';
$replace = preg_replace($pattern, '\\1', $str);
echo $replace . "\n";

$replace = preg_replace($pattern, '\\2', $str);
echo $replace . "\n";

输出:

abc
def

六、正则表达式常用PCRE函数

PHP官网的讲解已经很详细了,这里不再做多余的论述

执行正则表达式匹配 preg_match()

执行正则表达式全局匹配 preg_match_all()

执行一个正则表达式的搜索和替换 preg_replace()

执行一个正则表达式搜索并且使用一个回调进行替换 preg_replace_callback()

执行多个正则表达式搜索并且使用对应回调进行替换 preg_replace_callback_array()

通过一个正则表达式分隔字符串 preg_split()

七、应用实践

1. 正则表达式匹配中文

UTF-8汉字编码范围是 0x4e00-0x9fa5
在ANSI(GB2312)环境下,0xb0-0xf70xa1-0xfe

UTF-8要使用 u模式修正符 使模式字符串被当成 UTF-8
在ANSI(GB2312)环境下,要使用chr将Ascii码转换为字符

UTF-8

<?php

$str = &#39;中文&#39;;

$pattern = &#39;/[\x{4e00}-\x{9fa5}]/u&#39;;

preg_match($pattern, $str, $match);

var_dump($match);

ANSI(GB2312)

<?php

$str = &#39;中文&#39;;

$pattern = &#39;/[&#39;.chr(0xb0).&#39;-&#39;.chr(0xf7).&#39;][&#39;.chr(0xa1).&#39;-&#39;.chr(0xfe).&#39;]/&#39;;

preg_match($pattern, $str, $match);

var_dump($match);

2. 正则表达式匹配页面中所有img标签中的src的值。

<?php

$str = &#39;<img alt="高清大图" id="color" src="color.jpg" />';

$pattern = '/<img.*?src="(.*?)".*?\/?>/i';

preg_match($pattern, $str, $match);

var_dump($match);
文字 説明
(パターン) パターンに一致し、この一致を取得します。括弧の文字と一致させるには、\( または \) を使用します。
(?:pattern) パターンに一致しますが、一致結果が得られません。これは、これが非取得一致であることを意味し、後で使用するために保存されません。これは、「or」文字 (|) を使用して正規表現の一部を結合する場合に便利です。
たとえば、'industr(?:y|ies) は、'industry|industries' よりも単純な式です。
(?=pattern) 文字列一致パターンの先頭で先読み肯定アサート 検索文字列と一致します。これは非フェッチ一致です。つまり、後で使用するために一致をフェッチする必要はありません。
たとえば、「Windows(?=95|98|NT|2000)」は、「Windows2000」の「Windows」と一致しますが、「Windows3.1」の「Windows」と一致することはできません。プリフェッチでは文字は消費されません。つまり、一致が発生した後、次の一致の検索は、プリフェッチを含む文字の後に開始されるのではなく、最後の一致の直後に開始されます。
(?!pattern) 正負のアサート (ネガティブ アサート)、パターンに一致しない文字列の先頭に一致します。弦。これは非フェッチ一致です。つまり、後で使用するために一致をフェッチする必要はありません。
たとえば、「Windows(?!95|98|NT|2000)」は、「Windows3.1」の「Windows」と一致しますが、「Windows2000」の「Windows」と一致することはできません。プリフェッチでは文字は消費されません。つまり、一致が発生した後、次の一致の検索は、プリフェッチを含む文字の後に開始されるのではなく、最後の一致の直後に開始されます。
##(?<=pattern)たとえば、「(?<=95|98|NT|2000)Windows」は、「2000Windows」の「Windows」と一致しますが、「3.1Windows」の「Windows」と一致することはできません。

以上がPHPインタビューにおける正規表現の知識まとめ(超詳細)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。