preg_match如何匹配带有星号(*)的模式

7
preg_match('/te**ed/i', 'tested', $matches);

我遇到了以下错误:

错误:偏移量为3的位置没有可重复的内容

我该怎么做才能让模式实际包含 *


你是在尝试使用那个正则表达式匹配 tested 吗? - alex
我是指使用字面值“te**ed”。因此,我认为对其进行转义将解决问题 :) - sniper
4个回答

9

要使用字面上的星号,您需要用反斜杠进行转义。要匹配字面上的te**ed,您可以使用以下表达式:

preg_match('/te\*\*ed/i', 'tested', $matches); // no match (te**ed != tested)

但我怀疑这不是你想要的。如果你的意思是匹配任何字符,你需要使用.

preg_match('/te..ed/is', 'tested', $matches); // match

如果你真的想要任意两个小写字母,那么可以使用以下正则表达式:
preg_match('/te[a-z]{2}ed/i', 'tested', $matches); // match

我是指使用字面值“te**ed”。所以我认为对它进行转义会解决这个问题 :) - sniper
@sniper:说得好,但要认识到在给定的表达式中$matches仍将为空,而preg_match('/te\*\*ed/i', 'te**ed', $matches)将产生一个非空结果。 - Mark Elliot
啊...这正是我需要的!! :) 有没有什么内置函数可以快速转义 PHP 中的 "te**ed"? - sniper
@sniper:你可以使用preg_quote来转义所有正则表达式字符。 - Mark Elliot
太好了!问题解决了!我使用的最终正则表达式是:preg_match("/".preg_quote($search_string)."/i",$topic)。 - sniper
如果你真的想要任意两个小写字母...不,你正在使用一个不区分大小写的标志。 - mickmackusa

1
如果您想使用类似于星号的搜索,可以使用以下函数:
function match_string($pattern, $str)
{
  $pattern = preg_replace('/([^*])/e', 'preg_quote("$1", "/")', $pattern);
  $pattern = str_replace('*', '.*', $pattern);
  return (bool) preg_match('/^' . $pattern . '$/i', $str);
}

例子:

match_string("*world*","hello world") // returns true
match_string("world*","hello world") // returns false
match_string("*world","hello world") // returns true
match_string("world*","hello world") // returns false
match_string("*ello*w*","hello world") // returns true
match_string("*w*o*r*l*d*","hello world") // returns true

1

在 Viktor Kruglikov 的回答基础上,这是 PHP 7.3 实现此功能的方法:

private function match(string $pattern, string $target): bool
{
    $pattern = preg_replace_callback('/([^*])/', function($m) {return preg_quote($m[0], '/');}, $pattern);
    $pattern = str_replace('*', '.*', $pattern);
    return (bool) preg_match('/^' . $pattern . '$/i', $target);
}

1

在任何字符之前加上反斜杠将告诉PHP该字符应被视为普通字符,而非特殊的正则表达式字符。所以:

preg_match('/te\\**ed/i', 'tested', $matches);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接