【问题标题】:php regex match possible accented charactersphp正则表达式匹配可能的重音字符
【发布时间】:2015-10-16 02:33:57
【问题描述】:

我发现了很多关于这个的问题,但没有一个能帮助我解决我的具体问题。情况:我想用"blablebli"之类的东西搜索string,并能够找到与所有可能的重音变体("blablebli""blábleblí""blâblèbli"等)的匹配项一段文字。

我已经解决了相反的问题(找到一个我写的没有可能重音的单词)。但我想不出一种方法来实现我想要的。

这是我的工作代码。 (相关部分,这是 foreach 的一部分,所以我们只看到一个单词搜索):

$word="something";
$word = preg_quote(trim($word)); //Just in case
$word2 = $this->removeAccents($word); // Removed all accents
if(!empty($word)) {
    $sentence = "/(".$word.")|(".$word2.")/ui"; // Now I'm checking with and without accents.
    if (preg_match($sentence, $content)){
        echo "found";
    }
}

还有我的 removeAccents() 函数(我不确定我是否用 preg_replace() 覆盖了所有可能的口音。到目前为止它正在工作。如果有人检查我是否遗漏了什么,我将不胜感激):

function removeAccents($string)
{
    return preg_replace('/[\`\~\']/', '', iconv('UTF-8', 'ASCII//TRANSLIT', $string));
}

我要避免的事情:

  • 我知道我可以检查我的$word 并将所有a 替换为[aàáãâä] 和 与其他字母相同,但我不知道...它看到了一点 矫枉过正。
  • 当然我可以在我的if 中使用我自己的removeAccents() 函数 检查$content 不带重音的语句,例如:

    if (preg_match($sentence, $content) || preg_match($sentence, removeAccents($content)))
    

但我对第二种情况的问题是我想突出显示比赛后找到的单词。所以我不能更改我的$content

有什么方法可以改进我的preg_match() 以包含可能的重音字符?还是我应该使用上面的第一个选项?

【问题讨论】:

  • 我是土拨鼠,还是你昨天也问过这个问题?
  • 哈哈哈是的,我删除了那个,对不起。 17 小时后,它有大约 25 名观众,没有 cmets 或任何东西。它会被遗忘=/
  • 在源字符串上应用removeAccents,使用preg_matchPREG_OFFSET_CAPTURE选项来获取匹配的索引(或strpos,使用@987654343 @ 在原始字符串中进行替换。或者使用第一种方式,一点也不矫枉过正,可以通过strtr轻松完成。
  • @CasimiretHippolyte 谢谢。但是,如果我理解你所说的话,恐怕这不会 100% 起作用。将removeAccents() 应用于任何字符串后,我不能真正保证字母的数量是相同的。 IE:$content = "i'ts a sample" 将返回"its a sample",使索引不同。
  • Atm,我正在使用我提到的第一个解决方案,但我不喜欢它的原因是这段代码(如我所说)是foreach 的一部分。真正的搜索是在大量文本中寻找一个句子。我将搜索句子分解为单词,并根据匹配的单词数(并突出显示这些单词)向用户显示可能的结果。

标签: php regex search special-characters


【解决方案1】:

我会分解字符串,这样可以更容易地删除有问题的字符,类似于以下内容:

<?php

// Convert unicode input to NFKD form.
$str = Normalizer::normalize("blábleblí", Normalizer::FORM_KD);

// Remove all combining characters (https://en.wikipedia.org/wiki/Combining_character).
var_dump(preg_replace('/[\x{0300}-\x{036f}]/u', "", $str));

【讨论】:

  • 很好,我一定会用它代替iconv,谢谢!
【解决方案2】:

感谢大家的帮助,但我将使用我在问题中提出的第一个建议来结束它。再次感谢@CasimiretHippolyte 的耐心等待,让我意识到这并没有我想象的那么矫枉过正。

这是我使用的最终代码(首先是函数):

function removeAccents($string)
{
    return preg_replace('/[\x{0300}-\x{036f}]/u', '', Normalizer::normalize($string, Normalizer::FORM_KD));
}

function addAccents($string)
{
    $array1 = array('a', 'c', 'e', 'i' , 'n', 'o', 'u', 'y');
    $array2 = array('[aàáâãäå]','[cçćĉċč]','[eèéêë]','[iìíîï]','[nñ]','[oòóôõö]','[uùúûü]','[yýÿ]');

    return str_replace($array1, $array2, strtolower($string));
}

还有:

$word="something";
$word = preg_quote(trim($word)); //Just in case
$word2 = $this->addAccents($this->removeAccents($word)); //check all possible accents
if(!empty($word)) {
    $sentence = "/(".$word.")|(".$word2.")/ui"; // Now I'm checking my normal word and the possible variations of it.
    if (preg_match($sentence, $content)){
        echo "found";
    }
}

顺便说一句,我涵盖了我的国家(和其他一些国家)所有可能的口音。 addAccents()函数在使用前请检查是否需要改进。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-27
    • 2013-07-03
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    相关资源
    最近更新 更多