Регулярные выражения для обработки строк UTF-8 в P

При разработке многоязычных сайтов для 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]);
}
Скачать файл txt fb2
Добавил: Сталислав (14 янв 2009 г., 15:02)
Рейтинг: (0)
Прочитано: 6734