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 :
odTercih 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..dumphem 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, recodesize tam karakter haritanızı verecektir. El kitabına göre, bunu önce DEFAULT_CHARSETortam 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_CHARSETortamında değişken yerine kullanılır. Bu değişken tanımlanmamışsa, recodekü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, LANGve komut sayesinde tespit edilebilirlocale charmap.
Ayrıca kayda değer recode tam o bir API olduğunu :
Adlı program recodesadece 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, recodeprogramı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 POSIXve Cstandartlarıstrcoll() işlevi :
strcoll()Fonksiyon tarafından işaret dize karşılaştırmak zorundadır s1dize tarafından işaret etmek s2hem 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 POSIXkarakter sınıfları, zaten kullandığınız not ettik Cbu 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 < inputbir 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, recodeorijinal
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,
LANGUAGEveya LANGortam 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, recodegö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ımluitFiltrelemeden , odgeri 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 sequence değil , bence, muhtemelen çözmeye çalıştığınız sorunun özüdür.
GNU tr's mansayfası, [: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, sortancak bu bir arka uç programlama API için oldukça kullanışsız bir araç olacağını düşünüyorum.
recodebunu 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 gettextişlev kütüphanesini sunar ve bu sorunu en azından LC_MESSAGESbağlam için ele alabilecek gibi görünüyor :
- İşlev: char * bind_textdomain_codeset( const char *domainname,
const char *codeset)
bind_textdomain_codesetFonksiyon 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_codesetFonksiyonu 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+0300eşleşir a. Giriş olarak àkodlanırsa , aksanla U+00E0eş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 Tclkendi 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 localedefaş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 copyliste boyunca komutları fark etmeye başladım . Yukarıdaki dosya görünüyor copyiç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 greptabii 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 luitterminal UTF-8 ptyçeviri cihazı da var . Dönüştürülen tüm baytları bir dosyaya veya -cbasit bir |pipefiltre 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 3yerel 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 luitbu paketin bir parçasıdır.
Tcl_uni...İşlevleri de faydalı olabilir.
sadece biraz <tab>tamamlama ve manarama ve bu konuda çok şey öğrendim.
İle localedef- Eğer derlemek olabilir localessizin de I18Ndizindeki. Çı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 odokuyabilirsiniz - 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 odelbette 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 Perlve bir modülün nasıl düzgün bir şekilde yükleneceğini bilmiyorum. Ancak mansayfalar 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, I18Ntam olarak bilerek onları da işe alamayacağımı bilerek kaydırdığım birkaç tane var.
/usr/share/i18n/locales/i18ngeliyor ... tabii ki büyük ölçüde Unicode Karakter Veritabanından geliyor. Tabii ki, bir komuta sahip olmak güzel olurdu