Wondering why your preg_replace fails, even if you have used preg_quote?
Try adding the delimiter / - preg_quote($string, '/');
(PHP 4, PHP 5, PHP 7, PHP 8)
preg_quote — 正規表現文字をクオートする
preg_quote() は、str
を引数とし、正規表現構文の特殊文字の前にバックスラッシュを挿入します。
この関数は、実行時に生成される文字列をパターンとしてマッチングを行う必要があり、
その文字列には正規表現の特殊文字が含まれているかも知れない場合に有用です。
正規表現の特殊文字は、次のものです。
. \ + * ? [ ^ ] $ ( ) { } = ! < > | : - #
/
は正規表現の特殊文字ではないことに注意しましょう。
注意:
preg_quote() は、 preg_replace() などにおける $replacement 文字列に使うことを想定したものではありません。
str
入力文字列。
delimiter
オプションの delimiter
を指定すると、
ここで指定した文字もエスケープされます。これは、PCRE 関数が使用する
デリミタをエスケープする場合に便利です。/
がデリミタとしては
最も一般的に使用されています。
クォートされた (エスケープした) 文字列を返します。
バージョン | 説明 |
---|---|
7.3.0 |
# 文字がクォートされるようになりました。
|
7.2.0 |
delimiter は、nullable になりました。
|
例1 preg_quote() の例
<?php
$keywords = '$40 for a g3/400';
$keywords = preg_quote($keywords, '/');
echo $keywords; // \$40 for a g3\/400 を返します
?>
例2 テキスト内の単語の斜体変換
<?php
// この例では、preg_quote($word) を使って、アスタリスクが
// 正規表現での特殊な意味を帯びないようにしています
$textbody = "This book is *very* difficult to find.";
$word = "*very*";
$textbody = preg_replace ("/" . preg_quote($word, '/') . "/",
"<i>" . $word . "</i>",
$textbody);
?>
注意: この関数はバイナリデータに対応しています。
Wondering why your preg_replace fails, even if you have used preg_quote?
Try adding the delimiter / - preg_quote($string, '/');
I discovered that, in addition to escaping the special regular expression characters, preg_quote() encodes the NUL byte to its octal representation:
<?php
var_dump(preg_quote("\0"));
?>
Output:
string(4) "\000"
To escape characters with special meaning, like: .-[]() and so on, use \Q and \E.
For example:
<?php echo ( preg_match('/^'.( $myvar = 'te.t' ).'$/i', 'test') ? 'match' : 'nomatch' ); ?>
Will result in: match
But:
<?php echo ( preg_match('/^\Q'.( $myvar = 'te.t' ).'\E$/i', 'test') ? 'match' : 'nomatch' ); ?>
Will result in: nomatch
It should be noted that the forward slash is not escaped. Since many regexes are surrounded by forward slashes, if you have one in your regex as text you must escape it yourself otherwise it'll terminat the regex.
List of specials is incomplete:
--- sample code ---
$specials = '.\+*?[^]$(){}=!<>|:-';
for ($i = 0; $i <= 255; $i++) {
if (chr($i) !== preg_quote(chr($i))) {
printf("Character 0x%02x quoted%s\n",
$i,
(strpos($specials, chr($i)) === FALSE) ? ' (+)' : '');
} /* if */
} /* for */
--- sample code ---
--- output ---
Character 0x00 quoted (+)
Character 0x21 quoted
Character 0x24 quoted
Character 0x28 quoted
Character 0x29 quoted
Character 0x2a quoted
Character 0x2b quoted
Character 0x2d quoted
Character 0x2e quoted
Character 0x3a quoted
Character 0x3c quoted
Character 0x3d quoted
Character 0x3e quoted
Character 0x3f quoted
Character 0x5b quoted
Character 0x5c quoted
Character 0x5d quoted
Character 0x5e quoted
Character 0x7b quoted
Character 0x7c quoted
Character 0x7d quoted
--- output ---
To have a higher level control of what your pattern looks like, try T-Regx:
Pattern::inject('This is (my|our) pattern: @', [$_GET['name']]);
If you find yourself using too much of preg_quote(), it's a good sign you might want to use Prepared Patterns from T-Regx library: https://t-regx.com/docs/handling-user-input