Unix специальный регистр с учетом UTF-8 - PullRequest
3 голосов
/ 08 ноября 2011

Я нашел тему, касающуюся моего вопроса ( shell - разные версии UNIX сортируют регистр по-разному ), но он дает, так сказать, "противоположный" ответ.

У меня естьперепутал с переменной LANG, но не могу найти значение, которое достигает моей цели.

Например:

abc a
Abc d
Abc b
abc e
abæ g

Необходимо отсортировать по:

abc a
abc c
Abc b
Abc d
abæ g

Не это (то, что я в настоящее время получаю):

Abc b
Abc d
abc a
abc c
abæ g

И не это тоже (что я получаю, когда сортирую без учета регистра):

abc a
Abc b
abc c
Abc d
abæ g

Другими словами: мне нужна сортировка с учетом регистра по столбцу, в которой слова с заглавной буквой в верхнем регистре не сортируются в верхнем и верхнем / нижнем регистре версии одного и того же слова в зависимости от второго столбца.Обратите внимание, что мне нужна сортировка, чувствительная к UTF-8 (в данном случае я использовал датскую букву «æ», которая помещается в алфавит, например, так: «... vwxyzæøå»).

Я сортирую по двум столбцамиспользуя:

sort test.txt -k1,1 -k2,2

В любом случае, я могу сделать это безсортировка по сценарию?

1 Ответ

6 голосов
/ 09 ноября 2011

Вы не хотите, чтобы вещи в смешанном регистре в первом столбце смешивались вместе в зависимости от того, что имеет второй столбец, но это именно то, что дает сортировка без учета регистра.Это считает вещи, которые разделяют casefold, идентичными.

Сортировка этого набора записей Unicode:

abc a
Abc d
Abc b
abc e
abæ g

, конечно, такова:

abæ g
abc a
Abc b
Abc d
abc e

Это потому, что первая и вторая буквы «одинаковы»”( т.е. , их регистры одинаковы) во всех пяти строках, поэтому первая другая буква - третья, которая, как и æ, конечно, стоит перед буквой c, то есть то, что остальные четыре записи имеют в качестве своей третьейбуква.

С оставшимися строками у них у всех одинаковые первые три буквы, так что именно их четвертая буква является диспозитивной, давая теперь последовательность a, b, d, e.Пробелы (обычно) не имеют значения при сортировке в Юникоде, потому что это алфавитно-цифровая сортировка, а не сортировка по кодам.Мы рассматриваем здесь только буквы, если они не являются идентичными вплоть до регистра, и только тогда рассматриваются другие кодовые точки.

Вот как работает сортировка Unicode.

Алгоритм сопоставления Unicode не работаетобратите внимание на датский порядок, если вы не попросите об этом.Запись DUCET по умолчанию для этой кодовой точки ставит такие вещи, как æ и å, рядом с a, ø рядом с o.OED сортирует эти записи в следующем порядке:

 allergist
 allergy
 Allerød
 allers
 allethrin

Это потому, что o в «Allerød» следует за g в «аллергии» и предшествует s в «allers».Диакритические знаки имеют значение только в том случае, если все остальное одинаково, поэтому гипотетический «аллерок» предшествует «Аллероду», а гипотетический «аллерог» следует за ним, но предшествует «аллерсу».

Вот так работает сортировка в Юникоде.Скандинавы ненавидят это, потому что они думают, что это должно просто сделать то, что делают их уникальные национальные системы, но Unicode не склонен к определенному языку.Если вы хотите, чтобы ваши идиотсинкразии, вы должны использовать сортировку локали.Чтобы получить сортировку, специфичную для датской локали, такую ​​как:

abc a
Abc b
Abc d
abc e
abæ g

Вам нужно запустить сортировку с указанной датской локалью, но не в ломаном POSIX, а в Unicode.

Во-первых, вы должны отказаться от попытки использовать sort (1).Это хуже, чем бесполезно: это ненадежно и обманчиво.Если у вас есть данные Unicode, вы должны использовать сортировку Unicode, независимо от того, была ли изменена OED или изменена для вашей маленькой деревни.

Чтобы создать нормальный порядок Unicode, вы должны использовать:

#!/usr/bin/env perl
use strict;
use warnings;
use open qw(:std :utf8);
use utf8;

use Unicode::Collate;

my @lines = <<'End_of_Lines' =~ /\S.*\S\n/g;
    abc a
    Abc d
    Abc b
    abc e
    abæ g
End_of_Lines

my $collator = Unicode::Collate->new();
print $collator->sort(@lines);

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

#!/usr/bin/env perl    
use strict;
use warnings;
use open qw(:std :utf8);
use utf8;

use Unicode::Collate::Locale;

my @lines = <<'End_of_Lines' =~ /\S.*\S\n/g;
    abc a
    Abc d
    Abc b
    abc e
    abæ g
End_of_Lines

my $collator = Unicode::Collate::Locale->new(locale => "da");    
print $collator->sort(@lines);

Модуль Unicode::Collate включен в стандартную версию начиная с версии Perl v5.6.Модуль Unicode::Collate::Locale входит в стандартную версию начиная с версии Perl v5.14, но его легко установить из CPAN в более ранних выпусках:

 $ sudo perl -MCPAN -e "install Unicode::Collate::Locale"

Причина, по которой вы должны использовать Perl, заключается в том, что вы просто не можете доверять языковым стандартам поставщиков.работать в соответствии с Unicode Collation Algorithm, с изменениями локали или без них.Я никогда не видел двух разных систем, в которых они работают одинаково, а это означает, что по крайней мере одна из каждой пары сломана и, возможно, обе сломаны.Напротив, вы можете гарантировать, что UCA будет всегда вести себя одинаково независимо от того, где вы находитесь.Неважно, что может отображать ваш терминал.Это не заботится о шрифтах.Это не волнует, если вы перенаправлены.Неважно, какую оболочку вы используете.Неважно, будет ли ваша тетя Гертруда запускать код 5-го понедельника месяца.Это просто работает, и это работает одинаково каждый раз в любой ситуации.Используйте УЦА.Не принимайте замены.

Но только потому, что вы используетеUCA не означает, что вам нужно принять заказ по умолчанию. УЦА был разработан, чтобы быть супер поддающимся пошиву. Если вам нужна сортировка локали, это легко - и если есть данные CLDR для этой локали, это будет тривиально. Если вы хотите сделать что-то вроде названий книг и фильмов, или имен людей с фамилией, считающейся сильнее, чем имя, и с сортировкой всех шотландских Мак- и Мак-имен до M-, но независимо от друг друга, все эти вещи очень очень легко с УЦА. Все, что вы можете себе представить, может быть сделано, и обычно с удивительной легкостью. Дело в том, что с UCA вы всегда начинаете с поведения, которое гарантированно будет работать одинаково, независимо от платформы или предубеждений. Это означает, что вы можете положиться на то, как он работает, когда хотите применить к нему свои собственные настройки. Без этой гарантии все потеряно.

Вы можете получить готовую замену командной строки (ну, в некотором роде) для программы Unix sort (1), которая соответствует UCA здесь . Конечно, он не работает с полями, но делает немного больше.

...