EDIT: Я просто заметил, что вы на самом деле не указать который шаблон сопоставления языка вы использовали. Ну, я надеюсь, что решение Perl будет работать для вас, так как необходимые механики, вероятно, будут очень жесткими на любом другом языке. Плюс, если вы выполняете сопоставление с Unicode, Perl действительно лучший выбор для этой конкретной работы.
Когда переменная $rx
ниже устанавливается в соответствующий шаблон, этот маленький фрагмент кода Perl:
my $data = "foo1 and Πππ 語語語 done";
while ($data =~ /($rx)/g) {
print "Got string: '$1'\n";
}
Формирует этот вывод:
Got string: 'foo1 and '
Got string: 'Πππ '
Got string: '語語語 '
Got string: 'done'
То есть, он вытаскивает латинскую строку, греческую строку, строку Han и другую латинскую строку.Это довольно чертово, закрытое для того, что, на мой взгляд, вам действительно нужно.
Причина, по которой я не опубликовал это вчера, заключается в том, что я получаю странные отвалы ядра. Теперь я знаю, почему.
В моем решении используются лексические переменные внутри конструкции (??{...})
. Оказывается, что это неустойчиво до v5.17.1, и в лучшем случае работает только случайно. Он не работает на v5.17.0, но преуспевает в v5.18.0 RC0 и RC2. Поэтому я добавил use v5.17.1
, чтобы убедиться, что вы используете что-то достаточно недавнее, чтобы доверять этому подходу.
Во-первых, я решил, что вы действительно не хотите запускать все те же типы скриптов; вам нужен запуск всего того же типа скрипта плюс Обычный и унаследованный. В противном случае вы будете испорчены пунктуацией, пробелами и цифрами для Common, и комбинируя символы для Inherited. Я действительно не думаю, что вы хотите, чтобы те прервали ваш запуск «все того же скрипта», но если вы это сделаете, легко перестать рассматривать их.
Так что мы делаем это для первого символа, который имеет тип скрипта, отличный от Common или Inherited. Более того, мы извлекаем из него то, что на самом деле этот тип сценария, и используем эту информацию для создания нового шаблона, который представляет собой любое количество символов, тип сценария которых является либо общим, либо унаследованным, либо любым типом скрипта, который мы только что нашли и сохранили. Затем мы оцениваем этот новый шаблон и продолжаем.
Hey, I Это было волосатое, не так ли?
В программе, которую я собираюсь показать, я оставил в некоторых комментариях отладочные заявления, которые показывают только, что он делает. Если вы раскомментировать их, вы получите этот выход для последнего запуска, который должен помочь понять подход:
DEBUG: Got peekahead character f, U+0066
DEBUG: Scriptname is Latin
DEBUG: string to re-interpolate as regex is q{[\p{Script=Common}\p{Script=Inherited}\p{Script=Latin}]*}
Got string: 'foo1 and '
DEBUG: Got peekahead character Π, U+03a0
DEBUG: Scriptname is Greek
DEBUG: string to re-interpolate as regex is q{[\p{Script=Common}\p{Script=Inherited}\p{Script=Greek}]*}
Got string: 'Πππ '
DEBUG: Got peekahead character 語, U+8a9e
DEBUG: Scriptname is Han
DEBUG: string to re-interpolate as regex is q{[\p{Script=Common}\p{Script=Inherited}\p{Script=Han}]*}
Got string: '語語語 '
DEBUG: Got peekahead character d, U+0064
DEBUG: Scriptname is Latin
DEBUG: string to re-interpolate as regex is q{[\p{Script=Common}\p{Script=Inherited}\p{Script=Latin}]*}
Got string: 'done'
И вот наконец это большие волосатые сделки:
use v5.17.1;
use strict;
use warnings;
use warnings FATAL => "utf8";
use open qw(:std :utf8);
use utf8;
use Unicode::UCD qw(charscript);
# regex to match a string that's all of the
# same Script=XXX type
#
my $rx = qr{
(?=
[\p{Script=Common}\p{Script=Inherited}] *
(?<CAPTURE>
[^\p{Script=Common}\p{Script=Inherited}]
)
)
(??{
my $capture = $+{CAPTURE};
#####printf "DEBUG: Got peekahead character %s, U+%04x\n", $capture, ord $capture;
my $scriptname = charscript(ord $capture);
#####print "DEBUG: Scriptname is $scriptname\n";
my $run = q([\p{Script=Common}\p{Script=Inherited}\p{Script=)
. $scriptname
. q(}]*);
#####print "DEBUG: string to re-interpolate as regex is q{$run}\n";
$run;
})
}x;
my $data = "foo1 and Πππ 語語語 done";
$| = 1;
while ($data =~ /($rx)/g) {
print "Got string: '$1'\n";
}
Да, там Oughta быть лучший способ. Я не думаю, что есть.
Так что пока, наслаждайтесь.
Закрыть, но не совсем то же самое: http://stackoverflow.com/questions/14942652/how-to-emulate-word-boundary-when-using-unicode-character-properties/14942906#14942906 Мой ответ - это граница для один класс символов (и это относится к любому классу символов). Ваш вопрос о границе между любым языком. – nhahtdh
@nhahtdh: Спасибо. Я удивлен, что не нашел ваш вопрос в своих поисках. – hippietrail
Я думаю, что каждый должен прочитать раздел 2 этого: http://www.unicode.org/reports/tr24/ – nhahtdh