Документация  >  Общее  >  Регулярные выражения для обработки строк UTF-8 в PHP

При разработке многоязычных сайтов для HTML-страниц наиболее удобней и предпочтительней использовать кодировку UTF-8, обеспечивающую поддержку всех или почти всех существующих языков и кодирующую ASCII-символы (латинский алфавит, цифры и специальные символы) одним байтом, а национальные алфавиты — несколькими. Таким образом, кодировка UTF-8 имеет переменную физическую длину каждого символа. В связи с этим иногда возникают проблемы при программировании мультиязычных сайтов.

К примеру, в языке программирования PHP функции strlen и substr выдают некорректные результаты, если в строке имеются символы национального алфавита (поскольку предназначены для работы с однобайтовой кодировкой). Конечно же, в PHP существуют такие функции как mb_strlen и mb_susbtr, специально предназначенные для работы с мультибайтовыми строками. Но, по умолчанию поддержка Multibyte String Functions в PHP выключена, что автоматически ограничивает выбор хостинга для проектируемого сайта. Кроме того, при подключении модуля mb_string указывается набор поддерживаемых языков. А потому существует вероятность, что требуемого Вам языка может не оказаться в списке поддерживаемых.

Впрочем, существует другое, более удобное и гибкое решение проблемы. Воспользовавшись функциями PCRE, корректно воспринимающими кодировку UTF-8, можно написать свои функции utf8_strlen и utf8_substr:

function utf8_strlen($s)
{
    return preg_match_all('/./u', $s, $tmp);
}

function utf8_substr($s, $offset, $len = 'all')
{
    if ($offset<0) $offset = utf8_strlen($s) + $offset;
    if ($len!='all')
    {
        if ($len<0) $len = utf8_strlen($s) - $offset + $len;
        $xlen = utf8_strlen($s) - $offset;
        $len = ($len>$xlen) ? $xlen : $len;
        preg_match('/^.{' . $offset . '}(.{0,'.$len.'})/us', $s, $tmp);
    }
    else
    {
        preg_match('/^.{' . $offset . '}(.*)/us', $s, $tmp);
    }
    return (isset($tmp[1])) ? $tmp[1] : false;
}

Продолжая тему работы со строками в кодировке UTF-8, рассмотрим еще несколько функций, работающих без установленного в PHP расширения Multibyte String Functions, а именно utf8_strpos и utf8_substr_count:

function utf8_strpos($haystack, $needle, $offset = 0)
{
    # get substring (if isset offset param)
    $offset = ($offset<0) ? 0 : $offset;
    if ($offset>0)
    {
        preg_match('/^.{' . $offset . '}(.*)/us', $haystack, $dummy);
        $haystack = (isset($dummy[1])) ? $dummy[1] : '';
    }

    # get relative pos
    $p = strpos($haystack, $needle);
    if ($haystack=='' or $p===false) return false;
    $r = $offset;
    $i = 0;

    # calc real pos
    while($i<$p)
    {
        if (ord($haystack[$i])<128)
        {
            # ascii symbol
            $i = $i + 1;
        }
        else
        {
            # non-ascii symbol with variable length
            # (handling first byte)
            $bvalue = decbin(ord($haystack[$i]));       
            $i = $i + strlen(preg_replace('/^(1+)(.+)$/', '\1', $bvalue));
        }
        $r++;
    }
    return $r;
}

function utf8_substr_count($h, $n)
{
    # preparing $n for using in reg. ex.
    $n = preg_quote($n, '/');

    # select all matches
    preg_match_all('/' . $n . '/u', $h, $dummy);
    return count($dummy[0]);
}

ControlStyle,
12.05.2006.

Вернуться к списку

Добавить в закладки