是否有正则表达式匹配包含和不包含特殊字符的特定字符串?特殊字符不敏感,可以这么说。
与céra
匹配cera
,反之亦然。
有什么想法吗?
编辑:我想匹配具有和不带特殊/重音字符的特定字符串。不只是任何字符串/字符。
测试示例:
$clientName = 'céra';
$this->search = 'cera';
$compareClientName = strtolower(iconv('utf-8', 'ascii//TRANSLIT', $clientName));
$this->search = strtolower($this->search);
if (strpos($compareClientName, $this->search) !== false)
{
$clientName = preg_replace('/(.*?)('.$this->search.')(.*?)/iu', '$1<span class="highlight">$2</span>$3', $clientName);
}
输出:<span class="highlight">céra</span>
如您所见,我想突出显示特定的搜索字符串。但是,我仍然想要显示匹配字符串的原始(重音)字符。
我猜不得不以某种方式将其与Michael Sivolobov's answer结合起来。
我想我必须使用单独的preg_match()
和preg_replace()
,对吧?
答案 0 :(得分:8)
您可以使用\p{L}
模式匹配任何字母。
您必须在正则表达式后使用u
修饰符才能启用unicode模式。
示例:/\p{L}+/u
修改:
尝试这样的事情。它应该用包含重音字母(单字符和双字符双字母)和非重音字母的搜索模式替换每个带有重音的字母。然后,您可以使用更正的搜索模式突出显示文本。
function mbStringToArray($string)
{
$strlen = mb_strlen($string);
while($strlen)
{
$array[] = mb_substr($string, 0, 1, "UTF-8");
$string = mb_substr($string, 1, $strlen, "UTF-8");
$strlen = mb_strlen($string);
}
return $array;
}
// I had to use this ugly function to remove accents as iconv didn't work properly on my test server.
function stripAccents($stripAccents){
return utf8_encode(strtr(utf8_decode($stripAccents),utf8_decode('àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ'),'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY'));
}
$clientName = 'céra';
$clientNameNoAccent = stripAccents($clientName);
$clientNameArray = mbStringToArray($clientName);
foreach($clientNameArray as $pos => &$char)
{
$charNA =$clientNameNoAccent[$pos];
if($char != $charNA)
{
$char = "(?:$char|$charNA|$charNA\p{M})";
}
}
$clientSearchPattern = implode($clientNameArray); // c(?:é|e|e\p{M})ra
$text = 'the client name is Céra but it could be Cera or céra too.';
$search = preg_replace('/(.*?)(' . $clientSearchPattern . ')(.*?)/iu', '$1<span class="highlight">$2</span>$3', $text);
echo $search; // the client name is <span class="highlight">Céra</span> but it could be <span class="highlight">Cera</span> or <span class="highlight">céra</span> too.
答案 1 :(得分:7)
如果您想知道某些字母上是否有某些重音或其他标记,您可以通过匹配模式\p{M}
<强>更新强>
您需要将模式中所有重音字母转换为替代组合:
E.g。 céra -> c(?:é|e|e\p{M})ra
为什么要添加e\p{M}
?因为你的字母é可以是Unicode中的一个字符,可以是两个字符(e和重音符号)的组合。 e\p{M}
将 e与严重重音(两个单独的Unicode字符)匹配
当您转换模式以匹配所有字符时,您可以在preg_match
答案 2 :(得分:2)
答案 3 :(得分:2)
当您在其中一条评论中标记时,您不需要正则表达式,因为目标是查找特定字符串。你为什么不用explode
?像那样:
$clientName = 'céra';
$this->search = 'cera';
$compareClientName = strtolower(iconv('utf-8', 'ascii//TRANSLIT', $clientName));
$this->search = strtolower($this->search);
$pieces = explode($compareClientName, $this->search);
if (count($pieces) > 1)
{
$clientName = implode('<span class="highlight">'.$clientName.'</span>', $pieces);
}
修改强>
如果您的$search
变量也可能包含特殊字符,为什么不给它translit
,并将mb_strpos
与$offset
一起使用?像这样:
$offset = 0;
$highlighted = '';
$len = mb_strlen($compareClientName, 'UTF-8');
while(($pos = mb_strpos($this->search, $compareClientName, $offset, 'UTF-8')) !== -1) {
$highlighted .= mb_substr($this->search, $offset, $pos-$offset, 'UTF-8').
'<span class="highlight">'.
mb_substr($this->search, $pos, $len, 'UTF-8').'</span>';
$offset = $pos + $len;
}
$highlighted .= mb_substr($this->search, $offset, 'UTF-8');
更新2:
使用mb_
函数代替简单strlen
等很重要。这是因为重音字符使用两个或更多字节存储;另外,请务必确保使用正确的编码,例如:
echo strlen('é');
> 2
echo mb_strlen('é');
> 2
echo mb_internal_encoding();
> ISO-8859-1
echo mb_strlen('é', 'UTF-8');
> 1
mb_internal_encoding('UTF-8');
echo mb_strlen('é');
> 1