Когда я use locale, некоторые символы из моей локали (et_EE.UTF-8) не совпадают с \w и я не вижу в этом никакой причины.
Помимо ASCII, в эстонском языке используются еще шесть символов:
õäöüšž
В моем тестовом сценарии ниже я использую их в $string с тремя дополнительными специальными символами ðŋц (которые не принадлежат эстонскому алфавиту).
use feature 'say';
use POSIX qw( locale_h );
{
use utf8;
my $string = "õäöüšž ðŋц";
binmode STDOUT, ":encoding(UTF-8)";
say "nothing";
say 'LOCALE: ', setlocale(LC_CTYPE), ' ', setlocale(LC_COLLATE);
say 'UC: ', uc( $string );
say 'SORT: ', sort( split(//, $string) );
say $string =~ m/\w/g;
say $string =~ m/\p{Word}/g;
say '';
}
{
use utf8;
use locale;
binmode STDOUT, ":encoding(UTF-8)";
my $string = "õäöüšž ðŋц";
say "locale";
say 'LOCALE: ', setlocale(LC_CTYPE), ' ', setlocale(LC_COLLATE);
say 'UC: ', uc( $string );
say 'SORT: ', sort( split(//, $string) );
say $string =~ m/\w/g;
say $string =~ m/\p{Word}/g;
say '';
}
{
use utf8::all;
my $string = "õäöüšž ðŋц";
say "utf8::all";
say 'LOCALE: ', setlocale(LC_CTYPE), ' ', setlocale(LC_COLLATE);
say 'UC: ', uc( $string );
say 'SORT: ', sort( split(//, $string) );
say $string =~ m/\w/g;
say $string =~ m/\p{Word}/g;
say '';
}
{
use utf8::all;
use locale;
my $string = "õäöüšž ðŋц";
say "utf8::all + locale";
say 'LOCALE: ', setlocale(LC_CTYPE), ' ', setlocale(LC_COLLATE);
say 'UC: ', uc( $string );
say 'SORT: ', sort( split(//, $string) );
say $string =~ m/\w/g;
say $string =~ m/\p{Word}/g;
say '';
}
Я пробовал с Perl 5.10.1 и 5.14.2, и оба дали мне такой результат:
nothing
LOCALE: et_EE.UTF-8 et_EE.UTF-8
UC: ÕÄÖÜŠŽ ÐŊЦ
SORT: äðõöüŋšžц
õäöüšžðŋц
õäöüšžðŋц
locale
LOCALE: et_EE.UTF-8 et_EE.UTF-8
UC: ÕÄÖÜŠŽ ÐŊЦ
SORT: ðŋšžõäöüц
šžŋц
õäöüšžðŋц
utf8::all
LOCALE: et_EE.UTF-8 et_EE.UTF-8
UC: ÕÄÖÜŠŽ ÐŊЦ
SORT: äðõöüŋšžц
õäöüšžðŋц
õäöüšžðŋц
utf8::all + locale
LOCALE: et_EE.UTF-8 et_EE.UTF-8
UC: ÕÄÖÜŠŽ ÐŊЦ
SORT: ðŋšžõäöüц
šžŋц
õäöüšžðŋц
Что не так, как я ожидал?
- Основная проблема: под
use localeя надеялся, что\wбудет соответствовать всем моим шести символам, но результатšžŋцдовольно странный. Зачем такие спички? Из perlrecharclass я прочитал:
Для кодовых точек выше 255 ... \w соответствует тому же, что и \p{Word} в этом диапазоне. ... Для кодовых точек ниже 256 ... если действуют правила локали ... \w соответствует собственному символу подчеркивания платформы плюс тому, что локаль считает буквенно-цифровым.
Таким образом, \w соответствует там символам выше 255, но не соответствует «всем, что локаль считает буквенно-цифровым». Почему? В то же время сортировка по локали работает нормально (а без локали - нет), результат ðŋšžõäöüц - правильный порядок, который показывает, что правильные символы представлены правильно. AFAIU, сортировка не могла бы работать нормально, не зная их «независимо от того, что локаль считает буквенно-цифровым». Или?
- я думал, что
setlocaleдает результат только под прагмой локали. Как я могу проверить, какая локаль эффективна для области? - я не ожидал, что все символы в каждом тестовом примере будут в верхнем регистре. AFAIU
ucиlcдолжны зависеть от локали. В первом случае я думал, что все они будут в нижнем регистре, но, используя локаль, я ждал, что первые шесть символов будут в верхнем регистре, а другие нет. Единственный случай, когда я ждал, чтобы все символы были в верхнем регистре, был третьим. Я вижу, что упускаю здесь что-то важное. К сожалению, теперь я нашел изlcдокументов: «В противном случае, если в EXPR установлен флаг UTF-8: для изменения регистра используется семантика Unicode». На моем$stringвсегда установлен флаг UTF-8, поэтому при написании я получил ответ.
Использование locale для сортировки и \p{Word} для сопоставления приемлемо для меня, но я все же воспользуюсь некоторыми подсказками: почему \w не работает так, как я ожидал?
use locale. Пожалуйста, пожалуйста, используйтеUnicode::Collate::Localeдля всех сопоставлений и сравнений, специфичных для вашей локали. Смотрите обновленный ответ ниже, чтобы узнать, как вы должны подходить к этому. ПОСЛЕДНЕЕ ПРИМЕЧАНИЕ: Теперь ваш\wтоже будет работать правильно. - person tchrist   schedule 23.02.2013