preg_match: 找不到尾随特殊字符的子字符串

preg_match: can't find substring which has trailing special characters

我有一个函数,它使用 preg_match 检查子字符串是否在另一个字符串中。 今天我意识到,如果子字符串有尾随特殊字符,如特殊正则表达式字符 (. \ + * ? [ ^ ] $ ( ) { } = ! < > | :-) 或 @,我的 preg_match 找不到子字符串,即使它在那里。

这有效,returns "A match was found."

$find = "website scripting";
$string =  "PHP is the website scripting language of choice.";

if (preg_match("/\b" . $find . "\b/i", $string)) {
    echo "A match was found.";
} else {
    echo "A match was not found.";
}

但这不,returns"A match was not found."

$find = "website scripting @";
$string =  "PHP is the website scripting @ language of choice.";

if (preg_match("/\b" . $find . "\b/i", $string)) {
    echo "A match was found.";
} else {
    echo "A match was not found.";
}

我试过preg_quote,但没有用。

感谢您的任何建议!

编辑:单词边界是必需的,这就是我使用 \b 的原因。我不想在 "smartphone".

中找到 "phone"

您可以只检查搜索词周围的字符是否不是带有环视的单词字符:

$find = "website scripting @";
$string =  "PHP is the website scripting @ language of choice.";

if (preg_match("/(?<!\w)" . preg_quote($find, '/') . "(?!\w)/i", $string)) {
    echo "A match was found.";
} else {
    echo "A match was not found.";
}

IDEONE demo

结果:A match was found.

请注意在 (?<!\w)(?!\w) 中与 \w 一起使用的双斜杠,因为您必须转义内插字符串中的正则表达式特殊字符。

preg_quote 函数是必要的,因为搜索词 - 据我所知 - 可以包含特殊字符,如果要作为文字字符进行匹配,则必须对其中一些字符进行转义。

更新

有一种方法可以在关键字周围巧妙地放置单词边界来构建正则表达式,但与上述方法相比,性能会更差。这是示例代码:

$string =  "PHP is the website scripting @ language of choice.";

$find = "website scripting @";
$find = preg_quote($find);
if (preg_match('/\w$/u', $find)) {   //  Setting trailing word boundary
    $find .= '\b'; 
} 
if (preg_match('/^\w/u', $find)) {   //  Setting leading word boundary
    $find = '\b' . $find;
}

if (preg_match("/" . $find . "/ui", $string)) {
    echo "A match was found.";
} else {
    echo "A match was not found.";
}

another IDEONE demo

如果您尝试从另一个字符串中查找一个字符串,您可以strpos()

例如。

<?php

$find = "website scripting";
$string =  "PHP is the website scripting language of choice.";

if (strpos($string,$find) !== false) {
    echo 'true';
} else {
    echo 'false';
}