SOLUSI AKHIR YANG MUNGKIN
Jadi saya telah mengambil semua informasi di bawah ini dan menghasilkan ini:
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
CATATAN :
Saya menggunakan od
sebagai filter terakhir di atas untuk preferensi dan karena saya tahu saya tidak akan bekerja dengan karakter multi-byte, yang tidak akan ditangani dengan benar. recode u2..dump
keduanya akan menghasilkan keluaran lebih seperti yang ditentukan dalam pertanyaan dan menangani karakter lebar dengan benar.
KELUARAN
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 PROGRAMMER
Seperti yang saya tunjukkan di bawah, recode
akan memberi Anda peta karakter lengkap Anda. Menurut manualnya, ia melakukan ini pertama sesuai dengan nilai saat ini dari DEFAULT_CHARSET
variabel lingkungan, atau, jika gagal, ia beroperasi persis seperti yang Anda tentukan:
Ketika nama rangkaian karakter dihilangkan atau dibiarkan kosong, nilai DEFAULT_CHARSET
variabel dalam lingkungan digunakan sebagai gantinya. Jika variabel ini tidak didefinisikan, recode
perpustakaan menggunakan pengkodean lokal saat ini. Pada sistem yang mendukung POSIX , ini tergantung pada nilai non-kosong pertama di antara variabel lingkungan LC_ALL, LC_CTYPE, LANG
dan dapat ditentukan melalui perintahlocale charmap.
Juga perlu diperhatikan recode
adalah bahwa ini adalah api :
Program bernama recode
hanyalah aplikasi perpustakaan pengodeannya. Perpustakaan pengodean ulang tersedia secara terpisah untuk program C lainnya. Cara yang baik untuk mendapatkan keakraban dengan perpustakaan pengodean ulang adalah untuk berkenalan dengan recode
program itu sendiri.
Untuk menggunakan perpustakaan pengodean ulang setelah diinstal, program C perlu memiliki baris:
#include <recode.h>
Untuk perbandingan string yang ramah internasional POSIX
dan C
standar mendefinisikan strcoll()
fungsi:
The strcoll()
Fungsi akan membandingkan string ditunjukkan oleh s1
ke string yang ditunjukkan oleh s2
, baik ditafsirkan sesuai dengan kategori LC_COLLATE dari lokal saat ini.
The strcoll()
Fungsi tidak akan mengubah pengaturan errno jika berhasil.
Karena tidak ada nilai balik yang dicadangkan untuk menunjukkan kesalahan, aplikasi yang ingin memeriksa situasi kesalahan harus menetapkan errno ke 0, lalu panggil
strcoll()
, lalu periksa errno.
Berikut ini adalah secara terpisah terletak contoh penggunaannya:
#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);
}
Mengenai POSIX
kelas karakter, Anda telah mencatat Anda menggunakan C
API untuk menemukannya. Untuk karakter dan kelas unicode Anda bisa menggunakan charset recode's
dump-with-names untuk mendapatkan hasil yang diinginkan. Dari manualnya lagi :
Misalnya, perintah tersebut recode l2..full < input
menyiratkan konversi yang diperlukan dari Latin-2 ke UCS-2, karena dump-with-names hanya terhubung dari UCS-2. Dalam kasus tersebut, recode
tidak menampilkan kode
Latin-2 asli di dump, hanya nilai UCS-2 yang sesuai . Untuk memberikan contoh yang lebih sederhana, perintah
echo 'Hello, world!' | recode us..dump
menghasilkan output berikut:
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)
Komentar deskriptif diberikan dalam bahasa Inggris dan ASCII, namun jika deskripsi bahasa Inggris tidak tersedia tetapi yang Prancis, maka deskripsi Perancis diberikan sebagai gantinya, menggunakan bahasa Latin-1. Namun, jika
variabel LANGUAGE
atau LANG
lingkungan dimulai dengan huruf fr , maka daftar preferensi akan ke Prancis ketika kedua deskripsi tersedia.
Menggunakan sintaksis yang mirip dengan yang di atas dikombinasikan dengan dataset tes yang disertakan saya bisa mendapatkan peta karakter saya sendiri dengan:
recode -q u8/test8..dump </dev/null
KELUARAN
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)
Tetapi untuk karakter umum, recode
tampaknya tidak perlu. Ini akan memberi Anda charset bernama untuk semua yang ada di charset 128 byte:
printf %b "$(printf \\%04o $(seq 128))" |
luit -c |
od -A n -t o1z -t a -w12
KELUARAN
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
Tentu saja, hanya 128-byte yang diwakili, tetapi itu karena lokal saya, utf-8 charmaps atau tidak, menggunakan charset ASCII dan tidak lebih. Jadi hanya itu yang saya dapat. Jika saya menjalankannya tanpa luit
menyaringnya, od
akan menggulungnya kembali dan mencetak peta yang sama lagi\0400.
Ada dua masalah utama dengan metode di atas. Pertama, ada susunan susunan sistem - untuk non-ASCII lokal nilai-nilai gigitan untuk rangkaian tidak hanya seq
mempengaruhi, yang, seperti yang saya pikirkan, kemungkinan merupakan inti dari masalah yang Anda coba selesaikan.
Yah, tr's man
halaman GNU menyatakan bahwa itu akan memperluas [:upper:]
[:lower:]
kelas secara berurutan - tapi itu tidak banyak.
Saya membayangkan beberapa solusi yang berat dapat diimplementasikan dengan sort
tetapi itu akan menjadi alat yang agak sulit untuk API pemrograman backend.
recode
akan melakukan hal ini dengan benar, tetapi Anda sepertinya tidak terlalu menyukai program tersebut tempo hari. Mungkin suntingan hari ini akan memberikan cahaya yang lebih bersahabat atau mungkin tidak.
GNU juga menawarkan gettext
fungsi perpustakaan, dan tampaknya mampu mengatasi masalah ini setidaknya untuk LC_MESSAGES
konteksnya:
- Fungsi: char * bind_textdomain_codeset
( const char *domainname,
const char *codeset
)
The bind_textdomain_codeset
fungsi dapat digunakan untuk menentukan set karakter output untuk pesan katalog untuk domain
domainname . The codeset Argumen harus valid codeset nama yang dapat digunakan untuk iconv_open fungsi, atau null pointer.
Jika parameter codeset adalah penunjuk nol, bind_textdomain_codeset
mengembalikan set kode yang saat ini dipilih untuk domain dengan nama
domainname . Ia mengembalikan NULL jika tidak ada kode yang dipilih.
The bind_textdomain_codeset
fungsi dapat digunakan beberapa kali. Jika digunakan beberapa kali dengan argumen domainname yang sama, panggilan selanjutnya menimpa pengaturan yang dibuat oleh yang sebelumnya.
The bind_textdomain_codeset
mengembalikan fungsi pointer ke string yang berisi nama codeset yang dipilih. String dialokasikan secara internal dalam fungsi dan tidak boleh diubah oleh pengguna. Jika sistem keluar dari inti selama eksekusi
bind_textdomain_codeset
, nilai kembali adalah NULL dan errno variabel global diatur sesuai.
Anda juga dapat menggunakan kategori karakter Unicode asli , yang independen terhadap bahasa dan melepaskan kelas POSIX, atau mungkin memanggil yang pertama untuk memberi Anda cukup informasi untuk mendefinisikan yang terakhir.
Selain komplikasi, Unicode juga membawa kemungkinan baru. Salah satunya adalah bahwa setiap karakter Unicode milik kategori tertentu . Anda dapat mencocokkan satu karakter yang termasuk dalam kategori "huruf" dengan
\p{L}
. Anda dapat mencocokkan satu karakter yang tidak termasuk dalam kategori itu \P{L}
.
Sekali lagi, "karakter" benar-benar berarti "titik kode Unicode". \p{L}
cocok dengan satu titik kode dalam kategori "huruf". Jika string input Anda à
dikodekan sebagai U+0061 U+0300
, string tersebut cocok a
tanpa aksen. Jika input à
dikodekan sebagai U+00E0
, itu cocok à
dengan aksen. Alasannya adalah bahwa kedua kode menunjuk U+0061 (a)
dan U+00E0 (à)
berada dalam kategori "huruf", sedangkan U+0300
berada dalam kategori "tanda".
Anda sekarang harus mengerti mengapa \P{M}\p{M}*+
itu setara dengan \X
.
\P{M}
cocok dengan titik kode yang bukan tanda menggabungkan, sedangkan \p{M}*+
cocok dengan nol atau lebih titik kode yang menggabungkan tanda. Untuk mencocokkan surat termasuk diakritik, gunakan \p{L}\p{M}*+
. Regex terakhir ini akan selalu cocok à
, terlepas dari bagaimana dikodekan. Kuantif posesif memastikan bahwa menelusuri kembali tidak menyebabkan \P{M}\p{M}*+
mencocokkan non-mark tanpa menggabungkan tanda yang mengikutinya, yang \X
tidak akan pernah berhasil.
Website yang sama yang memberikan informasi atas juga membahas Tcl
sendiri 's POSIX compliant implementasi regex yang mungkin cara lain untuk mencapai tujuan Anda.
Dan yang terakhir di antara solusi saya akan menyarankan agar Anda dapat menginterogasi LC_COLLATE
file itu sendiri untuk peta karakter sistem lengkap dan teratur . Ini mungkin tampaknya tidak mudah dilakukan, tetapi saya mencapai beberapa keberhasilan dengan yang berikut setelah mengkompilasinya localedef
seperti yang ditunjukkan di bawah ini:
<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
Memang, saat ini, cacat, tapi saya harap itu menunjukkan kemungkinan setidaknya.
DI BLUSH PERTAMA
strings $_/en_GB
#OUTPUT
int_select "<U0030><U0030>"
...
END LC_TELEPHONE
Itu benar-benar tidak terlihat banyak tetapi kemudian saya mulai memperhatikan copy
perintah di seluruh daftar. File di atas tampaknya copy
di "en_US" misalnya, dan satu lagi yang benar-benar besar yang tampaknya mereka semua bagikan pada tingkat tertentu iso_14651_t1_common
.
Cukup besar:
strings $_ | wc -c
#OUTPUT
431545
Inilah intro untuk /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>;
...
Anda dapat grep
melalui ini tentu saja, tetapi Anda mungkin hanya:
recode -lf gb
Sebagai gantinya. Anda akan mendapatkan sesuatu seperti ini:
Dec Oct Hex UCS2 Mne BS_4730
0 000 00 0000 NU null (nul)
1 001 01 0001 SH start of heading (soh)
...
... DAN LEBIH BANYAK
Ada juga perangkat terjemahan luit
terminal UTF-8 yang pty
saya kira berfungsi sebagai perantara untuk XTerms tanpa dukungan UTF-8. Ini menangani banyak switch - seperti mencatat semua byte yang dikonversi ke file atau -c
sebagai |pipe
filter sederhana .
Saya tidak pernah menyadari ada begitu banyak hal ini - peta karakter dan lokal dan semua itu. Ini tampaknya masalah yang sangat besar tapi saya kira itu semua terjadi di belakang layar. Ada - setidaknya di sistem saya - beberapa ratus man 3
hasil terkait untuk pencarian terkait lokal.
Dan juga ada:
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
...
Itu akan berlangsung untuk waktu yang sangat lama.
The Xlib
fungsi menangani ini semua waktu - luit
adalah bagian dari paket itu.
The Tcl_uni...
fungsi mungkin terbukti bermanfaat juga.
hanya sedikit <tab>
penyelesaian dan man
pencarian dan saya sudah belajar banyak tentang hal ini.
Dengan localedef
- Anda dapat mengkompilasi locales
dalam I18N
direktori Anda . Outputnya funky, dan tidak terlalu berguna - tidak seperti charmaps
sama sekali - tetapi Anda bisa mendapatkan format mentah seperti yang Anda tentukan di atas seperti yang saya lakukan:
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
Kemudian dengan od
Anda dapat membacanya - byte dan string:
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...<
...
Meskipun masih jauh dari memenangkan kontes kecantikan, itu adalah hasil yang dapat digunakan. Dan od
dapat dikonfigurasi seperti yang Anda inginkan juga, tentu saja.
Saya kira saya juga lupa tentang ini:
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
Saya mungkin lupa tentang mereka karena saya tidak bisa membuatnya bekerja. Saya tidak pernah menggunakan Perl
dan saya tidak tahu cara memuat modul dengan benar saya kira. Tapi man
halaman - halamannya terlihat cukup bagus. Bagaimanapun, ada sesuatu yang memberitahu saya Anda akan menemukan memanggil modul Perl setidaknya sedikit lebih sulit daripada saya. Dan, sekali lagi, ini sudah ada di komputer saya - dan saya bahkan tidak pernah menggunakan Perl. Ada juga beberapa I18N
yang saya gulir secara salah dengan mengetahui sepenuhnya bahwa saya tidak akan membuat mereka bekerja juga.
/usr/share/i18n/locales/i18n
... yang tentu saja sebagian besar berasal dari Database Karakter Unicode. Tentu saja, akan menyenangkan memiliki perintah