OLASI NİHAİ ÇÖZÜM
Bu yüzden aşağıdaki tüm bilgileri aldım ve bununla geldim:
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
NOT :
od
Tercih için yukarıdaki son filtre olarak kullanıyorum ve bildiğim için çok baytlık karakterlerle çalışmayacağım, bu da doğru şekilde işlemeyecek. recode u2..dump
hem soruda belirtildiği gibi daha fazla çıktı oluşturur, hem de geniş karakterleri doğru şekilde işler.
ÇIKTI
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
PROGRAMCI API'sı
Aşağıda gösterdiğim gibi, recode
size tam karakter haritanızı verecektir. El kitabına göre, bunu önce DEFAULT_CHARSET
ortam değişkeninin mevcut değerine göre yapar veya başarısız olursa, tam olarak belirttiğiniz gibi çalışır:
Bir zaman karakter kümesi adı ihmal edilebilir ya da boş bırakılır, değeri DEFAULT_CHARSET
ortamında değişken yerine kullanılır. Bu değişken tanımlanmamışsa, recode
kütüphane geçerli yerel ayarın kodlamasını kullanır .On POSIX uyumlu sistemlerde, bu ortam değişkenleri arasında ilk boş olmayan değerine bağlıdır LC_ALL, LC_CTYPE, LANG
ve komut sayesinde tespit edilebilirlocale charmap.
Ayrıca kayda değer recode
tam o bir API olduğunu :
Adlı program recode
sadece kayıt kütüphanesinin bir uygulamasıdır. Kayıt kütüphanesi diğer C programları için ayrı olarak mevcuttur. Kayıt kütüphanesine biraz aşina olmanın iyi bir yolu, recode
programın kendisini tanımaktır .
Kurulduktan sonra kayıt kütüphanesini kullanmak için bir C programının bir satırı olması gerekir:
#include <recode.h>
Uluslararası olarak uygun dize karşılaştırması için POSIX
ve C
standartlarıstrcoll()
işlevi :
strcoll()
Fonksiyon tarafından işaret dize karşılaştırmak zorundadır s1
dize tarafından işaret etmek s2
hem yerelin LC_COLLATE kategorisine uygun olarak yorumlanır.
strcoll()
Fonksiyon başarılı olursa errno ayarını değiştirmek olmayacaktır.
Bir hatayı belirtmek için hiçbir dönüş değeri ayrılmadığından, hata durumlarını kontrol etmek isteyen bir uygulama errno değerini 0 olarak ayarlamalı ve
strcoll()
.
İşte ise ayrı yer onun kullanım örneği:
#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);
}
İlgili POSIX
karakter sınıfları, zaten kullandığınız not ettik C
bu bulmak için API. Unicode karakter ve sınıflar için, istediğiniz çıktıyı almak üzere recode's
adlarla birlikte döküm karakter kümesini kullanabilirsiniz. Onun itibaren , manüel :
Örneğin, komut recode l2..full < input
bir gerekli dönüşüm eder Latince-2 için , UCS-2 olarak dökümü-ile-isimler yalnızca dışarı bağlanır UCS-2. Bu gibi durumlarda, recode
orijinal
Latin-2 kodlarını dökümde göstermez, sadece karşılık gelen UCS-2 değerlerini gösterir. Daha basit bir örnek vermek gerekirse, komut
echo 'Hello, world!' | recode us..dump
aşağıdaki çıktıyı üretir:
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)
Açıklayıcı yorum İngilizce ve ASCII olarak verilir, ancak İngilizce açıklama mevcut değilse, ancak Fransızca bir açıklama varsa, bunun yerine Latince-1 kullanılarak Fransızca açıklama verilir. Ancak,
LANGUAGE
veya LANG
ortam değişkeni fr harfleriyle başlıyorsa, her iki açıklama da mevcut olduğunda liste tercihi Fransızca'ya gider.
Dahil olan test veri kümesiyle birlikte yukarıdaki sözdizimini kullanarak kendi karakter eşlememi alabilirim:
recode -q u8/test8..dump </dev/null
ÇIKTI
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)
Ancak ortak karakterler için, recode
görünüşe göre gerekli değildir. Bu, 128 baytlık karakter kümesindeki her şey için size karakter adı vermelidir:
printf %b "$(printf \\%04o $(seq 128))" |
luit -c |
od -A n -t o1z -t a -w12
ÇIKTI
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
Tabii ki, sadece 128 bayt temsil edilir, ancak bunun nedeni, benim yerel ayarım , utf-8 charmap'ları ya da değil, ASCII karakter kümesini kullanıyor ve daha fazlası değil. Yani tüm elde ettiğim bu. Eğer onsuz koşsaydımluit
Filtrelemeden , od
geri dönüp aynı haritayı tekrar\0400.
Yine de, yukarıdaki yöntemle ilgili iki büyük sorun vardır. Birincisi, sistemin harmanlama sırası var - ASCII olmayan yerel ayarlar için, karakter kümelerinin ısırık değerleri sadece seq
uence değil , bence, muhtemelen çözmeye çalıştığınız sorunun özüdür.
GNU tr's man
sayfası, [:upper:]
[:lower:]
sınıfları sırayla genişleteceğini söylüyor - ancak bu çok fazla değil.
Bazı ağır-elle çözüm uygulanabilir, sort
ancak bu bir arka uç programlama API için oldukça kullanışsız bir araç olacağını düşünüyorum.
recode
bunu doğru bir şekilde yapacak, ama geçen gün programa çok aşık görünmüyordun. Belki bugünkü düzenlemeler ona daha dostça ışık tutacak ya da vermeyecektir.
GNU ayrıca gettext
işlev kütüphanesini sunar ve bu sorunu en azından LC_MESSAGES
bağlam için ele alabilecek gibi görünüyor :
- İşlev: char * bind_textdomain_codeset
( const char *domainname,
const char *codeset
)
bind_textdomain_codeset
Fonksiyon alanı için mesaj katalogları için çıkış karakter kümesi belirtmek için kullanılabilir
etkialaniadi . Karakterkümesi argümanı geçerli olmalıdır karakterkümesi kullanılabilir adı iconv_open fonksiyonu ya da bir boş gösterici.
Eğer karakterkümesi parametresi boş gösterici, bind_textdomain_codeset
o anda seçili döner karakterkümesi adı ile alan adı için
etkialaniadi . Henüz kod seti seçilmemişse NULL döndürür .
bind_textdomain_codeset
Fonksiyonu birkaç kez kullanılabilir. Aynı alan adı bağımsız değişkeniyle birden çok kez kullanılırsa, sonraki çağrı, öncekinin yaptığı ayarları geçersiz kılar.
bind_textdomain_codeset
İşlev seçilen karakterkümesi adını içeren bir dizi için bir işaretçiyi geri döndürmektedir. Dize işlevde dahili olarak ayrılır ve kullanıcı tarafından değiştirilmemelidir. Sistemin yürütülmesi sırasında çekirdeğin dışına çıkması durumunda
bind_textdomain_codeset
, dönüş değeri NULL olur ve errno genel değişkeni buna göre ayarlanır.
Ayrıca , dilden bağımsız olan ve POSIX sınıflarından tamamen ayrılan yerel Unicode karakter kategorilerini de kullanabilir veya ikincisini tanımlamanız için yeterli bilgi sağlamak üzere öncekine çağrı yapabilirsiniz.
Komplikasyonlara ek olarak, Unicode da yeni olasılıklar getiriyor. Birincisi, her Unicode karakterinin belirli bir kategoriye ait olmasıdır. "Harf" kategorisine ait tek bir karakteri ile eşleştirebilirsiniz
\p{L}
. Bu kategoriye ait olmayan tek bir karakteri ile eşleştirebilirsiniz \P{L}
.
Yine, "karakter" gerçekten "Unicode kod noktası" anlamına gelir. \p{L}
"letter" kategorisindeki tek bir kod noktasıyla eşleşir. Giriş dizeniz olarak à
kodlanırsa , aksan olmadan U+0061 U+0300
eşleşir a
. Giriş olarak à
kodlanırsa , aksanla U+00E0
eşleşir à
. Neden kodu noktaları hem olmasıdır U+0061 (a)
ve U+00E0 (à)
süre, kategori "harfi" içindedirU+0300
kategori "işareti" içindedir.
Şimdi neden \P{M}\p{M}*+
eşdeğer olduğunu anlamalısınız \X
.
\P{M}
birleştirme işareti olmayan bir kod noktasıyla eşleşirken, işaretleri birleştiren \p{M}*+
sıfır veya daha fazla kod noktasıyla eşleşir. Herhangi bir aksan işareti içeren bir harfi eşleştirmek için kullanın \p{L}\p{M}*+
. Bu son normal ifade à
, nasıl kodlandığından bağımsız olarak her zaman eşleşecektir . Sahip olunan nicelik belirleyici, geri \P{M}\p{M}*+
izlemenin, onu izleyen birleştirme işaretleri olmadan iz bırakmayan bir işaretle eşleşmemesini sağlar ve bu \X
da hiçbir zaman gerçekleşmez.
Yukarıdaki bilgileri sağlayan aynı web sitesi , hedefinize ulaşmanın başka bir yolu olabilecek Tcl
kendi POSIX uyumlu normal ifade uygulamasını da tartışıyor .
Ve son çözümler arasında LC_COLLATE
, tam ve sıralı sistem karakter haritası için dosyanın kendisini sorgulayabileceğinizi önereceğim . Bu kolayca yapılmayabilir, ancak localedef
aşağıda gösterildiği gibi derledikten sonra aşağıdakilerle bazı başarılar elde ettim :
<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
Kuşkusuz şu anda kusurlu ama umarım en azından olasılığı gösterir.
İLK FIRÇA
strings $_/en_GB
#OUTPUT
int_select "<U0030><U0030>"
...
END LC_TELEPHONE
Gerçekten çok fazla görünmüyordu ama sonra copy
liste boyunca komutları fark etmeye başladım . Yukarıdaki dosya görünüyor copy
içinde "en_US" Örneğin, bazı derecesi için başka gerçek büyük kimse onlar tüm pay görünüyor iso_14651_t1_common
.
Oldukça büyük:
strings $_ | wc -c
#OUTPUT
431545
İşte giriş /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>;
...
Sen olabilir grep
tabii Bu yolla, ama sadece belki:
recode -lf gb
Yerine. Bunun gibi bir şey elde edersiniz:
Dec Oct Hex UCS2 Mne BS_4730
0 000 00 0000 NU null (nul)
1 001 01 0001 SH start of heading (soh)
...
... VE DAHASI
Ayrıca UTF-8 desteği olmayan XTerm'ler için bir geçiş işlevi gören luit
terminal UTF-8 pty
çeviri cihazı da var . Dönüştürülen tüm baytları bir dosyaya veya -c
basit bir |pipe
filtre olarak günlüğe kaydetme gibi birçok anahtarı işler .
Yerliler ve karakter haritaları ve bunların hepsi için bu kadar çok şey olduğunu hiç fark etmedim. Bu görünüşe göre çok büyük bir anlaşma ama sanırım her şey perde arkasında sürüyor. - En azından sistemimde - man 3
yerel ayarlarla ilgili aramalar için birkaç yüz ilgili sonuç var.
Ayrıca:
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
...
Bu çok uzun bir süre devam edecek.
Xlib
- fonksiyonları bu kez tüm idare luit
bu paketin bir parçasıdır.
Tcl_uni...
İşlevleri de faydalı olabilir.
sadece biraz <tab>
tamamlama ve man
arama ve bu konuda çok şey öğrendim.
İle localedef
- Eğer derlemek olabilir locales
sizin de I18N
dizindeki. Çıktı korkak ve olağanüstü kullanışlı değil - hiç gibi değil charmaps
- ama tıpkı benim yaptığım gibi yukarıda belirttiğiniz gibi ham formatı alabilirsiniz:
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
Sonra ile od
okuyabilirsiniz - bayt ve dizeleri:
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...<
...
Bir güzellik yarışmasını kazanmanın çok uzun bir yolu olmasına rağmen, bu kullanılabilir çıktı. Ve od
elbette olmasını istediğiniz kadar yapılandırılabilir.
Bunları da unuttum sanırım:
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
Muhtemelen onları unuttum çünkü onları çalıştıramadım. Asla kullanmıyorum Perl
ve bir modülün nasıl düzgün bir şekilde yükleneceğini bilmiyorum. Ancak man
sayfalar oldukça hoş görünüyor. Her durumda, bir şey bana Perl modülünü aradığımı en azından I'den biraz daha az zor bulacağınızı söylüyor. Ve yine, bunlar zaten bilgisayarımdaydı - ve asla Perl bile kullanmıyorum. Ayrıca, I18N
tam olarak bilerek onları da işe alamayacağımı bilerek kaydırdığım birkaç tane var.
/usr/share/i18n/locales/i18n
geliyor ... tabii ki büyük ölçüde Unicode Karakter Veritabanından geliyor. Tabii ki, bir komuta sahip olmak güzel olurdu