МОЖЛИВО ЗАВІДКОВЕ РІШЕННЯ
Отож, я взяв усю нижченаведену інформацію і прийшов до цього:
for class in $(
locale -v LC_CTYPE |
sed 's/combin.*//;s/;/\n/g;q'
) ; do
printf "\n\t%s\n\n" $class
recode u2/test16 -q </dev/null |
tr -dc "[:$class:]" |
od -A n -t a -t o1z -w12
done
ПРИМІТКА :
Я використовую od
як фінальний фільтр вище для налаштування, і тому що я знаю, що я не буду працювати з багатобайтовими символами, з якими він не буде правильно працювати. recode u2..dump
обидва будуть генерувати вихід, схожий на вказаний у запитанні, і правильно обробляти широкі символи.
ВИХІД
upper
A B C D E F G H I J K L
101 102 103 104 105 106 107 110 111 112 113 114 >ABCDEFGHIJKL<
M N O P Q R S T U V W X
115 116 117 120 121 122 123 124 125 126 127 130 >MNOPQRSTUVWX<
Y Z
131 132 >YZ<
lower
a b c d e f g h i j k l
141 142 143 144 145 146 147 150 151 152 153 154 >abcdefghijkl<
m n o p q r s t u v w x
155 156 157 160 161 162 163 164 165 166 167 170 >mnopqrstuvwx<
y z
171 172 >yz<
alpha
A B C D E F G H I J K L
101 102 103 104 105 106 107 110 111 112 113 114 >ABCDEFGHIJKL<
M N O P Q R S T U V W X
115 116 117 120 121 122 123 124 125 126 127 130 >MNOPQRSTUVWX<
Y Z a b c d e f g h i j
131 132 141 142 143 144 145 146 147 150 151 152 >YZabcdefghij<
k l m n o p q r s t u v
153 154 155 156 157 160 161 162 163 164 165 166 >klmnopqrstuv<
w x y z
167 170 171 172 >wxyz<
digit
0 1 2 3 4 5 6 7 8 9
060 061 062 063 064 065 066 067 070 071 >0123456789<
xdigit
0 1 2 3 4 5 6 7 8 9 A B
060 061 062 063 064 065 066 067 070 071 101 102 >0123456789AB<
C D E F a b c d e f
103 104 105 106 141 142 143 144 145 146 >CDEFabcdef<
space
ht nl vt ff cr sp
011 012 013 014 015 040 >..... <
print
sp ! " # $ % & ' ( ) * +
040 041 042 043 044 045 046 047 050 051 052 053 > !"#$%&'()*+<
, - . / 0 1 2 3 4 5 6 7
054 055 056 057 060 061 062 063 064 065 066 067 >,-./01234567<
8 9 : ; < = > ? @ A B C
070 071 072 073 074 075 076 077 100 101 102 103 >89:;<=>?@ABC<
D E F G H I J K L M N O
104 105 106 107 110 111 112 113 114 115 116 117 >DEFGHIJKLMNO<
P Q R S T U V W X Y Z [
120 121 122 123 124 125 126 127 130 131 132 133 >PQRSTUVWXYZ[<
\ ] ^ _ ` a b c d e f g
134 135 136 137 140 141 142 143 144 145 146 147 >\]^_`abcdefg<
h i j k l m n o p q r s
150 151 152 153 154 155 156 157 160 161 162 163 >hijklmnopqrs<
t u v w x y z { | } ~
164 165 166 167 170 171 172 173 174 175 176 >tuvwxyz{|}~<
graph
! " # $ % & ' ( ) * + ,
041 042 043 044 045 046 047 050 051 052 053 054 >!"#$%&'()*+,<
- . / 0 1 2 3 4 5 6 7 8
055 056 057 060 061 062 063 064 065 066 067 070 >-./012345678<
9 : ; < = > ? @ A B C D
071 072 073 074 075 076 077 100 101 102 103 104 >9:;<=>?@ABCD<
E F G H I J K L M N O P
105 106 107 110 111 112 113 114 115 116 117 120 >EFGHIJKLMNOP<
Q R S T U V W X Y Z [ \
121 122 123 124 125 126 127 130 131 132 133 134 >QRSTUVWXYZ[\<
] ^ _ ` a b c d e f g h
135 136 137 140 141 142 143 144 145 146 147 150 >]^_`abcdefgh<
i j k l m n o p q r s t
151 152 153 154 155 156 157 160 161 162 163 164 >ijklmnopqrst<
u v w x y z { | } ~
165 166 167 170 171 172 173 174 175 176 >uvwxyz{|}~<
blank
ht sp
011 040 >. <
cntrl
nul soh stx etx eot enq ack bel bs ht nl vt
000 001 002 003 004 005 006 007 010 011 012 013 >............<
ff cr so si dle dc1 dc2 dc3 dc4 nak syn etb
014 015 016 017 020 021 022 023 024 025 026 027 >............<
can em sub esc fs gs rs us del
030 031 032 033 034 035 036 037 177 >.........<
punct
! " # $ % & ' ( ) * + ,
041 042 043 044 045 046 047 050 051 052 053 054 >!"#$%&'()*+,<
- . / : ; < = > ? @ [ \
055 056 057 072 073 074 075 076 077 100 133 134 >-./:;<=>?@[\<
] ^ _ ` { | } ~
135 136 137 140 173 174 175 176 >]^_`{|}~<
alnum
0 1 2 3 4 5 6 7 8 9 A B
060 061 062 063 064 065 066 067 070 071 101 102 >0123456789AB<
C D E F G H I J K L M N
103 104 105 106 107 110 111 112 113 114 115 116 >CDEFGHIJKLMN<
O P Q R S T U V W X Y Z
117 120 121 122 123 124 125 126 127 130 131 132 >OPQRSTUVWXYZ<
a b c d e f g h i j k l
141 142 143 144 145 146 147 150 151 152 153 154 >abcdefghijkl<
m n o p q r s t u v w x
155 156 157 160 161 162 163 164 165 166 167 170 >mnopqrstuvwx<
y z
API ПРОГРАММЕРА
Як я демонструю нижче, recode
надамо вам повну карту символів. Згідно з його посібником, він робить це спочатку відповідно до поточного значення DEFAULT_CHARSET
змінної середовища, або, якщо цього не відбувається, він працює саме так, як ви вказали:
Якщо ім'я шаблону опущено або залишено порожнім, DEFAULT_CHARSET
замість цього використовується значення змінної в середовищі. Якщо ця змінна не визначена, recode
бібліотека використовує кодування поточного локалу. Для систем, сумісних з POSIX , це залежить від першого не порожнього значення серед змінних оточуючих середовищ LC_ALL, LC_CTYPE, LANG
і може бути визначене за допомогою командиlocale charmap.
Також варто зазначити recode
, що це api :
Названа програма recode
- це лише додаток її бібліотеки перекодування. Бібліотека перекодування доступна окремо для інших програм C. Хороший спосіб ознайомитись з бібліотекою перекодування - це ознайомлення з recode
самою програмою.
Щоб використовувати бібліотеку перекодування після її встановлення, програма C повинна мати рядок:
#include <recode.h>
Для порівняння рядків з міжнародними стандартами Функція POSIX
та C
стандарти визначають strcoll()
:
strcoll()
Функція повинна порівнювати рядок , на яку вказує s1
на рядок , на яку вказує s2
, як інтерпретуються в залежності від обставин до LC_COLLATE категорії поточної локалі.
strcoll()
Функція не змінює настройки егто в разі успіху.
Оскільки значення вказівки не зарезервоване для вказівки на помилку, програма, яка бажає перевірити наявність помилок, повинна встановити errno на 0, потім зателефонувати
strcoll()
, а потім перевірити errno.
Ось окремо розташований приклад його використання:
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[15];
char str2[15];
int ret;
strcpy(str1, "abc");
strcpy(str2, "ABC");
ret = strcoll(str1, str2);
if(ret > 0)
{
printf("str1 is less than str2");
}
else if(ret < 0)
{
printf("str2 is less than str1");
}
else
{
printf("str1 is equal to str2");
}
return(0);
}
Щодо POSIX
класів символів, ви вже відзначили, що використовували C
API, щоб знайти їх. Для символів та класів unicode ви можете використовувати recode's
діапазон dump-with-names для отримання потрібного результату. З його посібника знову :
Наприклад, команда recode l2..full < input
передбачає необхідне перетворення з латиниці-2 в UCS-2, оскільки дамп-з-іменами підключено лише з UCS-2. У таких випадках recode
не відображаються оригінальні
коди Latin-2 на дамп, лише відповідні значення UCS-2 . Навести більш простий приклад - команда
echo 'Hello, world!' | recode us..dump
видає такий вихід:
UCS2 Mne Description
0048 H latin capital letter h
0065 e latin small letter e
006C l latin small letter l
006C l latin small letter l
006F o latin small letter o
002C , comma
0020 SP space
0077 w latin small letter w
006F o latin small letter o
0072 r latin small letter r
006C l latin small letter l
0064 d latin small letter d
0021 ! exclamation mark
000A LF line feed (lf)
Описовий коментар надається англійською та ASCII, але якщо англійський опис не доступний, але французький, то французький опис наводиться замість латинської-1. Однак, якщо
змінна LANGUAGE
або LANG
середовище починається з літер fr , то перелік параметрів переходить до французької, коли доступні обидва описи.
Використовуючи синтаксис, подібний до вищезгаданого, у поєднанні з тестовим набором даних, який я включаю, я можу отримати власну карту символів за допомогою:
recode -q u8/test8..dump </dev/null
ВИХІД
UCS2 Mne Description
0001 SH start of heading (soh)
0002 SX start of text (stx)
0003 EX end of text (etx)
...
002B + plus sign
002C , comma
002D - hyphen-minus
...
0043 C latin capital letter c
0044 D latin capital letter d
0045 E latin capital letter e
...
006B k latin small letter k
006C l latin small letter l
006D m latin small letter m
...
007B (! left curly bracket
007C !! vertical line
007D !) right curly bracket
007E '? tilde
007F DT delete (del)
Але для загальних персонажів, recode
мабуть , це не потрібно. Це повинно дати вам іменовані символи для всього в 128-байтовій діаграмі:
printf %b "$(printf \\%04o $(seq 128))" |
luit -c |
od -A n -t o1z -t a -w12
ВИХІД
001 002 003 004 005 006 007 010 011 012 013 014 >............<
soh stx etx eot enq ack bel bs ht nl vt ff
...
171 172 173 174 175 176 177 >yz{|}~.<
y z { | } ~ del
Звичайно, представлені лише 128- байтові , але це тому, що мій локал , utf-8 charmaps чи ні, використовує діаграму ASCII і більше нічого. Отже, це все, що я отримую. Якби я запустив його, не luit
фільтруючи його, od
повернув би його назад і знову надрукував би ту саму карту\0400.
Однак з вищевказаним методом є дві основні проблеми. По-перше, є порядок складання системи - для не-ASCII локалів значення укусів для діаграм не просто не залежать seq
, що, як я думаю, є, ймовірно, серцем проблеми, яку ви намагаєтеся вирішити.
Ну, на tr's man
сторінці GNU зазначено, що вона розширить [:upper:]
[:lower:]
класи по порядку - але це не багато.
Я думаю, що якесь важке рішення можна було б реалізувати, sort
але це було б досить громіздким інструментом для API програмування бекенду.
recode
зробить це правильно, але ви не здавались занадто закоханим у програму днями. Можливо, сьогоднішні редагування на це будуть кидати більш привітне світло, а може й ні.
GNU також пропонує gettext
бібліотеку функцій, і, здається, зможе вирішити цю проблему принаймні для LC_MESSAGES
контексту:
- Функція: char * bind_textdomain_codeset
( const char *domainname,
const char *codeset
)
bind_textdomain_codeset
Функція може бути використана для визначення набору символів для виведення каталогів повідомлень для домену
ім'я_домена . Аргумент набору коду має бути дійсним набором коду, яке можна використовувати для функції iconv_open , або нульовим вказівником.
Якщо Codeset параметр є покажчиком NULL, bind_textdomain_codeset
повертає вибрані кодування для домену з ім'ям
імя_доменом . Він повертає NULL, якщо ще не вибрано набір коду .
bind_textdomain_codeset
Функція може бути використана кілька разів. Якщо використовується декілька разів з одним і тим же аргументом доменного імені, більш пізній виклик перекриває налаштування, зроблені попереднім.
bind_textdomain_codeset
Функція повертає покажчик на рядок , що містить ім'я обраного кодування. Рядок виділяється внутрішньо у функції і не повинен змінюватися користувачем. Якщо під час виконання системи система вийшла з ядра
bind_textdomain_codeset
, значення повернення NULL і глобальна змінна errno встановлюється відповідно.
Ви також можете використовувати власні категорії символів Unicode , які не залежать від мови та взагалі відмовляються від класів POSIX, або, можливо, подзвонити першим, щоб надати достатньо інформації для визначення останньої.
Окрім ускладнень, Unicode також пропонує нові можливості. Одне полягає в тому, що кожен символ Unicode належить до певної категорії. Ви можете зіставити один символ, що належить до категорії "літери", за допомогою
\p{L}
. Ви можете зіставити одного символу, який не належить до цієї категорії \P{L}
.
Знову ж таки, "символ" дійсно означає "точку коду Unicode". \p{L}
відповідає одній кодовій точці в категорії "літера". Якщо ваш вхідний рядок à
кодується як U+0061 U+0300
, він відповідає a
без наголосу. Якщо вхід à
закодовано як U+00E0
, він збігається à
з наголосом. Причина полягає в тому, що як кодові точки, так U+0061 (a)
і U+00E0 (à)
знаходяться в категорії "літера", а U+0300
знаходяться в категорії "позначка".
Тепер вам слід зрозуміти, чому \P{M}\p{M}*+
це еквівалент \X
.
\P{M}
збігається з кодовою точкою, яка не є комбінуючою позначкою, тоді як \p{M}*+
відповідає нулю або більше кодових точок, що поєднують позначки. Щоб відповідати букві, що включає будь-яку діакритику, використовуйте \p{L}\p{M}*+
. Цей останній регулярний вираз завжди буде відповідати à
, незалежно від того, яким чином він кодується. Присвійний кількісний коефіцієнт гарантує, що зворотний трекінг не спричиняє \P{M}\p{M}*+
відповідності без позначення без комбінованих позначок, що слідують за ним, що \X
ніколи б не зробило.
Той самий веб-сайт, який надав вищевказану інформацію, також обговорює Tcl
власну реабілітаційну схему, сумісну з POSIX, що може бути ще одним способом досягнення вашої мети.
І останнє з рішень , я вважаю , що ви можете опитувати LC_COLLATE
сам файл для повного і в замовленні карти системи символів. Це може здатися нелегким, але я досяг певного успіху в наступному після компіляції, localedef
як показано нижче:
<LC_COLLATE od -j2K -a -w2048 -v |
tail -n2 |
cut -d' ' -f$(seq -s',' 4 2 2048) |
sed 's/nul\|\\0//g;s/ */ /g;:s;
s/\([^ ]\{1,3\}\) \1/\1/;ts;
s/\(\([^ ][^ ]* *\)\{16\}\)/\1\n/g'
dc1 dc2 dc3 dc4 nak syn etb can c fs c rs c sp ! "
# $ % & ' ( ) * + , - . / 0 1 2
3 4 5 6 7 8 9 : ; < = > ? @ A B
C D E F G H I J K L M N O P Q R
S T U V W X Y Z [ \ ] ^ _ ` a b
c d e f g h i j k l m n o p q r
s t u v w x y z { | } ~ del soh stx etx
eot enq ack bel c ht c vt cr c si dle dc1 del
Це, правда, наразі недоліки, але я сподіваюся, що він хоча б демонструє можливість.
НА ПЕРШОМУ БЛИЦІ
strings $_/en_GB
#OUTPUT
int_select "<U0030><U0030>"
...
END LC_TELEPHONE
Це насправді мало схоже, але тоді я почав помічати copy
команди у всьому списку. Вище файл , здається, copy
в «en_US» , наприклад, і ще один справжній великий , що здається , всі вони мають в якій - то мірою це iso_14651_t1_common
.
Він досить великий:
strings $_ | wc -c
#OUTPUT
431545
Ось вступ до /usr/share/i18n/locales/POSIX
:
# Territory:
# Revision: 1.1
# Date: 1997-03-15
# Application: general
# Users: general
# Repertoiremap: POSIX
# Charset: ISO646:1993
# Distribution and use is free, also for
# commercial purposes.
LC_CTYPE
# The following is the POSIX Locale LC_CTYPE.
# "alpha" is by default "upper" and "lower"
# "alnum" is by definiton "alpha" and "digit"
# "print" is by default "alnum", "punct" and the <U0020> character
# "graph" is by default "alnum" and "punct"
upper <U0041>;<U0042>;<U0043>;<U0044>;<U0045>;<U0046>;<U0047>;<U0048>;\
<U0049>;<U004A>;<U004B>;<U004C>;<U004D>;<U004E>;<U004F>;
...
Ви можете, grep
звичайно, через це, але ви можете просто:
recode -lf gb
Натомість. У вас вийде щось подібне:
Dec Oct Hex UCS2 Mne BS_4730
0 000 00 0000 NU null (nul)
1 001 01 0001 SH start of heading (soh)
...
... І БІЛЬШЕ
Є також luit
термінальний pty
пристрій перекладу UTF-8, я думаю, що він працює між XTerms без підтримки UTF-8. Він обробляє безліч комутаторів - наприклад, реєстрацію всіх перетворених байтів у файл або -c
як простий |pipe
фільтр.
Я ніколи не розумів, що в цьому є стільки - локальних і символьних карт і всього цього. Це, мабуть, дуже велика справа, але я гадаю, що все продовжується за лаштунками. Є, принаймні, в моїй системі - кілька сотень man 3
пов’язаних результатів для пошуку, пов’язаного з локальністю.
А також є:
zcat /usr/share/i18n/charmaps/UTF-8*gz | less
CHARMAP
<U0000> /x00 NULL
<U0001> /x01 START OF HEADING
<U0002> /x02 START OF TEXT
<U0003> /x03 END OF TEXT
<U0004> /x04 END OF TRANSMISSION
<U0005> /x05 ENQUIRY
...
Це триватиме дуже довго.
Ці Xlib
функції обробляють весь цей час - luit
це частина цього пакету.
Ці Tcl_uni...
функції можуть виявитися корисними , а також.
лише невелике <tab>
завершення та man
пошуки, і я дуже багато чого навчився на цій темі.
З localedef
- ви можете скласти locales
файл у своєму I18N
каталозі. Вихід є прикольним і не надзвичайно корисним - зовсім не таким, як charmaps
у всіх - але ви можете отримати необроблений формат так само, як ви вказали вище, як і я:
mkdir -p dir && cd $_ ; localedef -f UTF-8 -i en_GB ./
ls -l
total 1508
drwxr-xr-x 1 mikeserv mikeserv 30 May 6 18:35 LC_MESSAGES
-rw-r--r-- 1 mikeserv mikeserv 146 May 6 18:35 LC_ADDRESS
-rw-r--r-- 1 mikeserv mikeserv 1243766 May 6 18:35 LC_COLLATE
-rw-r--r-- 1 mikeserv mikeserv 256420 May 6 18:35 LC_CTYPE
-rw-r--r-- 1 mikeserv mikeserv 376 May 6 18:35 LC_IDENTIFICATION
-rw-r--r-- 1 mikeserv mikeserv 23 May 6 18:35 LC_MEASUREMENT
-rw-r--r-- 1 mikeserv mikeserv 290 May 6 18:35 LC_MONETARY
-rw-r--r-- 1 mikeserv mikeserv 77 May 6 18:35 LC_NAME
-rw-r--r-- 1 mikeserv mikeserv 54 May 6 18:35 LC_NUMERIC
-rw-r--r-- 1 mikeserv mikeserv 34 May 6 18:35 LC_PAPER
-rw-r--r-- 1 mikeserv mikeserv 56 May 6 18:35 LC_TELEPHONE
-rw-r--r-- 1 mikeserv mikeserv 2470 May 6 18:35 LC_TIME
Потім od
ви можете прочитати його - байти та рядки:
od -An -a -t u1z -w12 LC_COLLATE | less
etb dle enq sp dc3 nul nul nul T nul nul nul
23 16 5 32 19 0 0 0 84 0 0 0 >... ....T...<
...
Хоча від перемоги в конкурсі краси це далеко, це корисний результат. І od
це так само конфігурується, як ви хочете, щоб це було, звичайно.
Я думаю, я також забув про це:
perl -mLocale
-- Perl module --
Locale::Codes Locale::Codes::LangFam Locale::Codes::Script_Retired
Locale::Codes::Constants Locale::Codes::LangFam_Codes Locale::Country
Locale::Codes::Country Locale::Codes::LangFam_Retired Locale::Currency
Locale::Codes::Country_Codes Locale::Codes::LangVar Locale::Language
Locale::Codes::Country_Retired Locale::Codes::LangVar_Codes Locale::Maketext
Locale::Codes::Currency Locale::Codes::LangVar_Retired Locale::Maketext::Guts
Locale::Codes::Currency_Codes Locale::Codes::Language Locale::Maketext::GutsLoader
Locale::Codes::Currency_Retired Locale::Codes::Language_Codes Locale::Maketext::Simple
Locale::Codes::LangExt Locale::Codes::Language_Retired Locale::Script
Locale::Codes::LangExt_Codes Locale::Codes::Script Locale::gettext
Locale::Codes::LangExt_Retired Locale::Codes::Script_Codes locale
Я, мабуть, забув про них, бо не міг змусити їх працювати. Я ніколи не використовую Perl
і, напевно, не знаю, як правильно завантажити модуль. Але man
сторінки виглядають досить приємно. У будь-якому випадку, щось підказує мені, що вам зателефонувати на модуль Perl принаймні трохи складніше, ніж я. І, знову ж таки, вони вже були на моєму комп’ютері - і я навіть ніколи не використовую Perl. Також є кілька таких, I18N
які я задумливо прокручував, знаючи добре, що я також не змусив їх працювати.
/usr/share/i18n/locales/i18n
... що, звичайно, походить з бази даних символів Unicode. Звичайно, було б непогано мати команду