【问题标题】:Regex to ignore accents? PHP正则表达式忽略重音? PHP
【发布时间】:2012-05-15 16:09:54
【问题描述】:

有没有办法制作一个忽略重音的正则表达式?

例如:

preg_replace("/$word/i", "<b>$word</b>", $str);

正则表达式中的“i”是忽略大小写敏感的,但有什么可以匹配的,例如
javaJávã

我确实尝试制作 $str 的副本,将内容更改为无重音字符串并找到所有出现的索引。但是这两个字符串的索引似乎不同,即使它只是没有重音。

(我做了一个研究,但我只能找到如何从字符串中删除重音)

【问题讨论】:

  • 第一个问题很好,顺便说一句:)

标签: php regex preg-replace diacritics


【解决方案1】:

Java 和 Jávã 是不同的词,正则表达式不支持删除重音符号,但您可以在正则表达式中包含所有可能的带有或不带有重音符号的字符组合。

点赞preg_replace("/java|Jávã|jáva|javã/i", "&lt;b&gt;$word&lt;/b&gt;", $str);

祝你好运!

【讨论】:

    【解决方案2】:

    我不认为,有这样的方法。这将取决于语言环境,您可能需要先使用“/u”开关以在模式字符串中启用 UTF-8。

    我可能会做这样的事情。

    function prepare($pattern)
    {
       $replacements = Array("a" => "[áàäâ]",
                             "e" => "[éèëê]" ...);
       return str_replace(array_keys($replacements), $replacements, $pattern);  
    }
    
    pcre_replace("/(" . prepare($word) . ")/ui", "<b>\\1</b>", $str);
    

    在您的情况下,索引是不同的,因为除非您使用 mb_string,否则您可能正在处理每个字符使用多个字节的 UTF-8。

    【讨论】:

    • 非常感谢您的回答:)
    • 还有一个问题:有什么办法可以用它找到的东西代替吗?如果 javaJávã 匹配,我想将 Jávã 放在 而不是 java 之间,这就是搜索.
    • 我已将此解决方案实现为高亮功能。你可以在这里看到它:stackoverflow.com/questions/27932260/…
    • 我们有什么办法可以将此解决方案应用于所有变音符号?
    【解决方案3】:

    Regex 不是适合您的工具。

    您正在寻找的答案是strtr() 函数。

    此函数替换字符串中的指定字符,正是您要查找的。​​p>

    在您的示例中,Jávã,您可以像这样使用strtr() 调用:

    $replacements = array('á'=>'a', 'ã'=>'a');
    $output = strtr("Jávã",$replacements);
    

    $output 现在将包含Java

    当然,您需要一个更大的$replacements 数组来处理您想要处理的所有字符。有关人们如何使用它的一些示例,请参阅我链接的手册页。

    请注意,没有一个简单的字符列表,因为首先它会很大,其次,相同的起始字符可能需要在不同的上下文或语言中进行不同的翻译。

    希望对您有所帮助。

    【讨论】:

      【解决方案4】:
      <?php
      
      if (!function_exists('htmlspecialchars_decode')) {
          function htmlspecialchars_decode($text) {
              return str_replace(array('&lt;','&gt;','&quot;','&amp;'),array('<','>','"','&'),$text);
          }
      }
      
      function removeMarkings($text) 
      {
          $text=htmlentities($text);    
          // components (key+value = entity name, replace with key)
          $table1=array(
              'a'=>'grave|acute|circ|tilde|uml|ring',
              'ae'=>'lig',
              'c'=>'cedil',
              'e'=>'grave|acute|circ|uml',
              'i'=>'grave|acute|circ|uml',
              'n'=>'tilde',
              'o'=>'grave|acute|circ|tilde|uml|slash',
              's'=>'zlig', // maybe szlig=>ss would be more accurate?
              'u'=>'grave|acute|circ|uml',
              'y'=>'acute'
          );
      
          // direct (key = entity, replace with value)
          $table2=array(
              '&ETH;'=>'D',   // not sure about these character replacements
              '&eth;'=>'d',   // is an ð pronounced like a 'd'?
              '&THORN;'=>'B', // is a þ pronounced like a 'b'?
              '&thorn;'=>'b'  // don't think so, but the symbols looked like a d,b so...
          );
      
          foreach ($table1 as $k=>$v) $text=preg_replace("/&($k)($v);/i",'\1',$text);
          $text=str_replace(array_keys($table2),$table2,$text);    
          return htmlspecialchars_decode($text);
      }
      
      $text="Here two words, one in normal way and another in accent mode java and jává and me searched with java and it found both occurences(higlighted form this sentence) java and jává<br/>";
      $find="java"; //The word going to higlight,trying to higlight both java and jává by this seacrh word
      $text=utf8_decode($text);
      $find=removeMarkings(utf8_decode($find)); $len=strlen($find);
      preg_match_all('/\b'.preg_quote($find).'\b/i', removeMarkings($text), $matches, PREG_OFFSET_CAPTURE);
      $start=0; $newtext="";
      foreach ($matches[0] as $m) {
          $pos=$m[1];
          $newtext.=substr($text,$start,$pos-$start);
          $newtext.="<b>".substr($text,$pos,$len)."</b>";
          $start=$pos+$len;
      }
      $newtext.=substr($text,$start);
      echo "<blockquote>",$newtext,"</blockquote>";
      
      ?>
      

      我认为这样的东西会对你有所帮助,我是从论坛上得到的……看看吧。

      【讨论】:

      • 这是一个有趣的方法。确实,$text=preg_replace('/&amp;(.)[^;]+;/i','$1',htmlentities($text)); 在 99% 的情况下都可以正常工作。
      【解决方案5】:

      设置适当的语言环境(例如 fr_FR)并使用strcoll 函数来比较忽略重音的字符串。

      【讨论】:

      • 但这如何回答 OP 的问题?他想匹配正则表达式中的字符串。