Как выявить суррогатные пары в String в Perl

Я работаю над базой кода perl для проверки ввода клиента, моя цель - заблокировать суррогатные символы.

Моя мысль заключается в том, чтобы сначала закодировать ввод клиента как UTF-16 и

 foreach my $messageChar (@MessageChars) {
   my $messageCharUTF16 = Encode::encode("UTF-16", $messageChar);
   if (($messageCharUTF16 >= 0xD800 && $messageCharUTF16 <= 0xDBFF)|( $messageCharUTF16 >= 0xDC00 && $messageCharUTF16 <= 0xDFFF)) {
      // Then we have surrogate pairs       
   }   
 }

Однако я не получаю правильные значения UTF-16 из Encode::encode.

Как я могу выявить суррогатные пары? Есть ли простой способ проверить, содержит ли строка суррогатные символы в Perl?


person Dengke Liu    schedule 22.03.2018    source источник


Ответы (1)


Мне непонятно, что вы хотите проверить, поэтому я рассмотрю обе возможности.


Чтобы проверить, содержит ли декодированная строка что-либо из U+D800..U+DFFF

Официальный стандарт Unicode говорит, что никакие формы UTF, включая UTF-16, не могут кодировать эти кодовые точки, и Perl обязывает.

$ perl -e'use open ":std", ":encoding(UTF-8)"; print "ABC\N{U+D800}DEF\n";'
Unicode surrogate U+D800 is illegal in UTF-8 at -e line 1.
"\x{d800}" does not map to utf8 at -e line 1.
ABC\x{D800}DEF

Чтобы проверить эти символы, вы можете использовать

$str =~ /[\x{D800}-\x{DFFF}]/

Чтобы проверить наличие ошибок кодирования, вы можете использовать

eval { encode("UTF-8", $str, Encode::FB_CROAK | Encode::LEAVE_SRC); 1 }

Чтобы проверить, содержит ли декодированная строка символ выше U+FFFF

Символы выше U + FFFF не могут быть закодированы с использованием UCS-2 и требуют суррогатных символов для кодирования с использованием UTF-16.

$ perl -e'use open ":std", ":encoding(UTF-16le)"; print "\N{U+10000}";' | od -t x2
0000000 d800 dc00
0000004

Чтобы проверить эти символы, вы можете использовать

$str =~ /[^\0-\x{FFFF}]/
person ikegami    schedule 22.03.2018