Я написал небольшую функцию на Perl, которая берет строку и проверяет ее длину без пробелов. основной код выглядит следующим образом:
sub foo
{
use utf8;
my @wordsArray = split(/ /, $_[0]));
my $result = length(join('', @wordsArray));
return $result;
}
Когда я предоставляю этой функции строку, содержащую специальные символы (например, буквы иврита), она отлично работает. проблема начинается, когда я использую значение из столбца MySql с набором символов utf8mb4: в таком случае вычисляемое значение выше, чем значение в предыдущем примере.
Я догадываюсь, почему происходит такое поведение: спецсимволы в таблице записаны в 4-байтовом формате, и, таким образом, каждая буква считается как два символа в кодировке utf8.
Кто-нибудь знает, как можно решить вышеуказанное, чтобы я получил правильное количество символов из строки, исходящей из таблицы БД, определенной как utf8mb4?
ИЗМЕНИТЬ:
Еще немного информации о приведенном выше коде:
Столбец БД, используемый в качестве аргумента функции, имеет тип VARCHAR(1000) с сопоставлением utf8mb4_unicode_ci. Я извлекаю строку через соединение MySql, настроенное следующим образом:
$mySql = DBI->connect(
"DBI:mysql:$db_info{'database'}:$db_info{'hostname'};mysql_multi_statements=1;",
"$db_info{'user'}",
"$db_info{'password'}",
{'RaiseError' => 1,'AutoCommit' => 0});
...
$mySql->do("set names utf8mb4");
пример значения данных будет "שלום עולם" (что на иврите означает "Hello World").
1) При вызове foo($request->{VALUE});
(где ЗНАЧЕНИЕ — данные столбца из БД) результат равен 16 (где каждый символ иврита считается за два символа, а один пробел между ними не учитывается). Самосвал в данном случае это:
$VAR1 = "\327\251\327\234\327\225\327\235 \327\242\327\225\327\234\327\235";
2) При вызове foo("שלום עולם");
:
при объявлении
use utf8;
результатом будет 8 (поскольку в этой строке 8 видимых символов). Дампер (Useqq=1) в этом случае:$VAR1 = "\x{5e9}\x{5dc}\x{5d5}\x{5dd} \x{5e2}\x{5d5}\x{5dc}\x{5dd}";
если не объявлять `use utf8;', результат равен 16 и аналогичен случаю отправки значения из БД:
$VAR1 = "\327\251\327\234\327\225\327\235 \327\242\327\225\327\234\327\235";
Похоже, мне нужно найти способ преобразования полученного значения в UTF8, прежде чем начать с ним работать.
sub foo { $_[0] =~ tr/ //c; }
- person Borodin   schedule 17.05.2015