Быстрый способ найти разницу между двумя строками Unicode в Perl vol 2 - PullRequest
0 голосов
/ 06 декабря 2018

В оригинальном вопрос по той же теме круто и быстро ответ , но более новые perls больше не поддерживают такой вариант использования, они выдают предупреждение об устаревании:

Use of strings with code points over 0xFF as arguments to bitwise xor (^) operator is deprecated

Как найти различия между двумя строками Unicode в Perl?

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

Кодирование строк Unicode до октетов в кодировке UTF-8 должно работать без предупреждений:

#!perl
use strict;
use warnings;
use Encode 'encode';
use charnames ':full'; # just for the example below

    binmode STDOUT, ':encoding(UTF-8)';

sub cmp_unicode {
    my ($s1, $s2) = @_;
    $s1 = encode( 'UTF-8' => $s1 );
    $s2 = encode( 'UTF-8' => $s2 );
    my $mask = $s1^$s2;
    while ($mask =~ /[^\0]/g) {
        print substr($s1,$-[0],1), ' ', substr($s2,$-[0],1), ' ', $-[0], "\n";
    }
}

cmp_unicode( 'abc', 'def' );
cmp_unicode( "   <\N{SNOWMAN}>", "   <\N{FATHER CHRISTMAS}>" );
cmp_unicode( "   <\N{LATIN CAPITAL LETTER A WITH DIAERESIS}!!>", "   <...>" );

Индексы будут индексами октетов, а не индексами в строках Unicode.Решение @ ikegami по декодированию в UTF-32 намного лучше, так как находит индексы в исходных строках Unicode.Ниже приведен адаптированный пример:

#!perl
use strict;
use warnings;
use Encode 'encode';
use charnames ':full'; # just for the example below

    binmode STDOUT, ':encoding(UTF-32)';

sub cmp_unicode {
    my ($s1, $s2) = @_;
    $s1_32 = encode( 'UTF-32' => $s1 );
    $s2_32 = encode( 'UTF-32' => $s2 );
    my $mask = $s1_32^$s2_32;
    while ($mask =~ /\G(?:\0{4})*+(.{4})/sg) {
    printf "%d %s %s\n",
       $pos,
       substr($s1, $pos, 1),
       substr($s2, $pos, 1);
    }
}

cmp_unicode( 'abc', 'def' );
cmp_unicode( "   <\N{SNOWMAN}>", "   <\N{FATHER CHRISTMAS}>" );
cmp_unicode( "   <\N{LATIN CAPITAL LETTER A WITH DIAERESIS}!!>", "   <...>" );

Является ли обновление до 32-разрядного (в четыре раза больше данных) все еще достаточно быстрым или вас просто не волнует положение символов, решать вам.

0 голосов
/ 06 декабря 2018

Кодирование строки с использованием кодировки фиксированной ширины.

my $s1 = encode('UTF-32', $original_string_1);
my $s2 = encode('UTF-32', $original_string_2);

my $mask = $s1 ^ $s2;
while ($mask =~ /\G(?:\0{4})*+(.{4})/sg) {
    my $pos = $-[1] / 4;
    printf "%d %s %s\n",
       $pos,
       substr($original_string_1, $pos, 1),
       substr($original_string_2, $pos, 1);
}

Конечно, это все еще имеет проблемы с использованием XOR (имеет проблемы с вставками и удалениями, а не с заменами). Algorithm :: Diff обеспечивает что-то, что «повторно синхронизируется».

Также следует опасаться, что не все кодовые точки подходят для самостоятельной печати.Управляющие символы, знаки продолжения и другие кодовые точки, вероятно, не должны распечатываться напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...