Geçerli yerel ayarda belirli bir karakter sınıfındaki karakterlerin listesini alma komutu


18

Ne belirli bir karakter sınıfında tüm karakterlerin (gibi bir listesini almak için bir yol olabilir blank, alpha, digitgeçerli yerelde ...).

Örneğin,

LC_ALL=en_GB.UTF-8 that-command blank

İdeal olarak, Debian sistemimde şöyle bir şey görüntülenir:

      09 U+0009 HORIZONTAL TAB
      20 U+0020 SPACE
e1 9a 80 U+1680 OGHAM SPACE MARK
e1 a0 8e U+180E MONGOLIAN VOWEL SEPARATOR
e2 80 80 U+2000 EN QUAD
e2 80 81 U+2001 EM QUAD
e2 80 82 U+2002 EN SPACE
e2 80 83 U+2003 EM SPACE
e2 80 84 U+2004 THREE-PER-EM SPACE
e2 80 85 U+2005 FOUR-PER-EM SPACE
e2 80 86 U+2006 SIX-PER-EM SPACE
e2 80 88 U+2008 PUNCTUATION SPACE
e2 80 89 U+2009 THIN SPACE
e2 80 8a U+200A HAIR SPACE
e2 81 9f U+205F MEDIUM MATHEMATICAL SPACE
e3 80 80 U+3000 IDEOGRAPHIC SPACE

Ve C yerelinde şöyle bir şey görüntülenebilir:

09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE

Yani, karakterin yerel ayardaki bayt dizileri cinsinden temsili (ilk örnekte UTF-8 ve ikincisinde tek bayt gibi), eşdeğer Unicode karakter kod noktası ve bir açıklama.

bağlam

Güvenlik açığı uzun süre yamanıp açığa çıktığına göre, biraz bağlam ekleyebilirim.

Bu soruyu CVE 2014-0475'i araştırırken sordum . glibckullanıcının LC_ALL=../../../../tmp/evil-localestandart sistem yerel arama yoluna göre çözülen böyle yerel ayarları kullanmasına ve böylece herhangi bir dosyayı yerel ayar tanımı olarak kullanmasına izin vermesinde bir hata vardı .

Ben sahtekar yerel yaratabilecek hariç çoğu karakterler karakter charset başına tek bayt ile örneğin s, hve birkaç başka kabul edildi boşlukları ve o yapmak istiyorum bashçalıştırmak shtipik bir Debian ayrıştırılırken /etc/bash.bashrcdosya (ve bu a üzerinde kabuk erişmek için kullanılabilir gitÖrneğin sağlanan barındırma sunucusu bash, gitsunucu kullanıcısının oturum açma kabuğu olarak kullanılır ve sshsunucunun LC_*/ LANGdeğişkenleri kabul ettiği ve saldırganın sunucuya dosya yükleyebileceği).

Şimdi, LC_CTYPE(derlenmiş bir yerel ayar) bulduğumda /tmp/evil, bunun nasıl sahtekar olduğunu ve hangi şekilde olduğunu nasıl öğrenebilirim.

Yani amacım bu yerel tanımın derlemesini kaldırmak ve eğer değilse, en azından belirli bir karakter sınıfında hangi karakterin (kodlamaları ile birlikte) olduğunu bilmek.

Bunu akılda tutarak:

  • Yerel ayarın ( /usr/share/i18n/localeDebian'dakiler gibi yerel ayarların) kaynak dosyalarına bakan çözümlerin benim durumumda hiçbir faydası yoktur.
  • Unicode karakter özellikleri önemsizdir. Sadece yerel ayarın ne dediğini önemsiyorum. Debian sisteminde, iki UTF-8 sistem yerel ayarı arasında bile, haydut olanlar hariç, bir sınıftaki karakterlerin listesi farklı olabilir.
  • Araçlar gibi recode, pythonya da perlkarakter dönüşüm yerel ayar daha farklı bir şekilde dönüşüm yapmak (do ve pratikte) onlar may olarak kullanılamaz için / bayt / çok bayt yapmak.

Çoğu lokal için sonuçta (glibc ile) LC_CTYPE şeylerinden /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
derobert

@ derobert, evet, locale(en azından GNU olanı) birçok kategoride saklanan bilgilerin birçoğunu alırken , LC_CTYPE ve LC_COLLATE için en önemlisi olmayan şeyler. Bu bilgileri almak veya yerel bilgileri derlemek için gizli bir API olup olmadığını merak ediyorum.
Stéphane Chazelas

Evet - bu bilgiyi çözümleyebilirsin - Nihayet düzenlememi tamamladım. Muhtemelen kurmuş olduğunuz birkaç komut var - en azından yaptım ve onlar hakkında bile bilmiyordum. Umut ediyorum bu yardım eder. Özellikle recodeve uconvsize aradığınızı söylediklerinizi verebilir. Muhtemelen bile luitve odsanırım ...
mikeserv

Çok iyi! Bu perlhiç ihtiyacınız olmadığı anlamına geliyor , sanırım.
mikeserv

Temelde benim charset ayıklamak mümkün görünmektedir LC_CTYPEsadece birlikte od -A n -t c <LC_CTYPE | tsortMuhtemelen zaten denedim, ama daha önce hiç duymadım ediyorum ve ben içinden okuyordu infove bu hatırlattı - ve işin görünüyor. Ayrıca var ptxama bence daha az alakalı. Her neyse, denemediyseniz ve bunu yapmaya karar verdiyseniz - adil uyarı - biraz sabır gerektirir. lehman.cuny.edu/cgi-bin/man-cgi?tsort+1
mikeserv

Yanıtlar:


7

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.


1
Hepsi çok güzel ve yararlı bilgiler, ancak i18nşu anda kullandığım yerel ayarı oluşturmak için kullanılmış veya edilmemiş kaynak dosyalar (in ) hakkında bilgi veriyor . Yerel ayar bilgileri büyük olasılıkla /usr/lib/locale/locale-archiveveya adresinden geliyor /some/dir/LC_CTYPEve bu , benim bulunduğum dosyalarda depolanan yerel ayarımla ilgili bölüm .
Stéphane Chazelas

@StephaneChezales - bu yüzden sadece LC_STUFFarşivden çıkarın localedef- bunu da yapar. Sanırım bunu da gösterebilirim. Ayrıca ve hemen hemen her şeyi stringsveya odgeri kalanını da görebilirsiniz. Yine de yaptım. Ama bu arada - charmaps vardır ve - yerel sen şu anda kullanmakta localedefolduğu yanı bildirir. Ayrıca bu da ne recodeyapar.
mikeserv

Temelde, sistem kütüphanelerinin karakter sınıfı bilgilerini sorgulamak için ne yapabileceğimizi elle yapabileceğimizi söylüyorsunuz, ancak bunu güvenilir bir şekilde yapmak için binlerce kod satırına ihtiyacınız olacak ve sonuç sisteme özgü olacaktır. (ortamı sistem kitaplığıyla aynı şekilde ayrıştırma (LOCPATH, LANG, LANGUAGE, LC_CTYPE ..., verileri nerede arayacağınızı belirleme, ayıklama ...). Arşivden nasıl dosya çıkaracağımı göremiyorum Yine de localedef ile.
Stéphane Chazelas

@StephaneChazelas - Sana elle yapmak önermiyoruz - Sistem gibi ikilileri kullanarak - Bir bilgisayar ile bunu önermek od, recode, uconvve gerisini. Ama bu benim hatamdı - onu localedefçıkartan değil, recodeolacak. Kontrol etmelisin info recode- ve recodetablo komutunun yanı sıra aynı şey var - ve işleri aynı şekilde idare edecek diye düşünüyorum. Sadece setini ince havadan çekmiyor. Her halükarda, bu perlmodüller için yüksek umutlarım vardı - hiç denediniz mi?
mikeserv

1
Geçerli yerel ayarda belirli bir karakter sınıfındaki karakterlerin listesini almak için bir API varsa, özellikle aradığım şey budur. Bunu nasıl yapacağınızı gösterebilirseniz, cevabı kabul edeceğim. Düşünebildiğim tek şey (ve sorumdaki "beklenen çıktıyı" nasıl elde ettiğimi) iswblank(3)olası tüm karakter değerleri için kullanmaktır .
Stéphane Chazelas

1

GNU, FreeBSD veya Solaris sistemlerinde en azından bu kaba kuvvet yaklaşımı işe yarar:

#include <wctype.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  unsigned long i;
  int need_init;
  wctype_t type;
  FILE* to_perl;

  setlocale(LC_ALL,"");
  if (argc != 2) {
    fprintf(stderr, "Usage: %s <type>\n", (argc?argv[0] : "???"));
    exit(1);
  }
  if (!(type = wctype(argv[1]))) {
    fprintf(stderr, "Invalid type: \"%s\"\n", argv[1]);
    exit(1);
  }

  need_init = wctomb(0, 0);

  to_perl = popen("perl -Mcharnames=full -ane '"
                  "printf \"%17s U+%04X %s\n\", join(\" \", @F[1..$#F]),"
                  "$F[0], charnames::viacode($F[0])'", "w");

#ifdef SUPPORT_ROGUE_LOCALES
  for(i=0; i<=0x7fffffff; i++) {
#else
  for(i=0; i<=0x10ffff; i++) {
    if (i == 0xd800) i = 0xe000; /* skip UTF-16 surrogates */
#endif
    if (iswctype(i, type)) {
      int n;
      unsigned char buf[1024];

      if (need_init) wctomb(0, 0);
      n = wctomb(buf, i);

      if (n > 0) {
        int c;
        fprintf(to_perl, "%lu", i);
        for (c = 0; c < n; c++)
          fprintf(to_perl, " %02X", buf[c]);
        putc('\n', to_perl);
      }
    }
  }
  pclose(to_perl);
  return 0;
}

C / POSIX başına, wchar_tUnicode ile hiçbir ilgisi olmayan ve yalnızca sistemin yerel ayarı tarafından desteklenen tüm karakterleri kapsaması garanti edilen opak bir türken, pratikte, Unicode'u destekleyen çoğu sistemde, değerler Unicode kod noktalarına karşılık gelir ve yerel ayarların tanımları da Unicode'a dayanmaktadır.

Unicode, bilinen tüm karakter kümelerinin üst kümesidir, bu nedenle Unicode'daki tüm geçerli kod noktaları (0 ila 0xD7FF ve 0xE000 ila 0x10FFFF) arasında döngü yapıldığında, en azından belirli bir karakter kümesi tarafından desteklenen tüm karakterler listelenmelidir.

Burada, belirli bir türden hangilerinin olduğunu kontrol etmek ve yerel ayarın kodlamasındaki kodlanmış formuna dönüştürmek için sistemin yerel standart API'sini kullanıyoruz. Biz kullanmak perlve charnamesmodülü yalnızca belirli bir Unicode kod noktasıyla adını alır.

ISO-2022-JP gibi durum bilgisi olan kodlamalar kullanan yerel ayarlarda, kodlanan formun varsayılan başlangıç ​​durumundan görüntülendiğinden emin oluruz.

Durum bilgisi olan bir karakter kodlamasıyla yerelleri yükleyen bir sistem bulamadım, ancak en azından GNU sistemlerinde, haydut bir yerel ayar yapılabilir (ve en azından GNU araçları bu şekilde düzgün çalışmıyor) yerel ayarlar). Örneğin, normal bir ja_JPyerel ayarla ISO-2022-JP kullanan özel bir yerel ayarla şunu elde ederim:

$ LOCPATH=$PWD LC_ALL=ja_JP.ISO-2022-JP ~/list-type blank
       09 U+0009 CHARACTER TABULATION
       20 U+0020 SPACE
   1B 24 42 21 21 U+3000 IDEOGRAPHIC SPACE

İle karşılaştırmak:

$ LC_ALL=ja_JP.eucjp ~/list-type blank
       09 U+0009 CHARACTER TABULATION
       20 U+0020 SPACE
    A1 A1 U+3000 IDEOGRAPHIC SPACE

ISO-2022-JP'de, 1B 24 42sekans ( \e$B) ASCII'den karakterlerin 2 (7 bit) bayt olarak ifade edildiği bir duruma geçer (burada IDEOGRAPHIC SPACE için 21 21). EUCJP'deyken aynı bayttır, ancak durum geçişi , A1 = 21 | 0x80daha vatansız hale getiren 8. biti ( ) çevirerek yapılır .

Bu, durum bilgisi olan kodlamalarda, belirli bir karakteri yazmanın birkaç yolu olduğu anlamına gelir (örneğin, bu durum değiştirme dizilerinin birkaçını ekleyerek ) ve yukarıdaki kodla gösterilen sıra yalnızca bunlardan biridir (bir baştaki kurallı kod) Varsayılan durum).

Normal bir yerel ayar için, karakterler 0..0xD7FF, 0xE000..0x10FFFF dışında olamazken, dolandırıcı bir yerel ayar için, wchar_t tarafından desteklenen aralıktaki herhangi bir karakter olabilir. Örneğin, U + DCBA veya U + 12345678 karakterlerinin (veya izin verildiyse karakter olacağı) boşluk olduğu bir yerel ayar oluşturabilirim . Bu yüzden bu kodu -D SUPPORT_ROGUE_LOCALESbunları kapsayacak şekilde derlemek istersiniz , ancak bu, tüm listeyi taramak için çok daha fazla zaman gerektirdiği anlamına gelir.

@ Mikeserv'in çözümünü recodekendi dönüşümlerini kullandığı için kullanamadım, artık korunmuyor ve sadece 0xFFFF'e kadar Unicode karakterleri destekliyor ve GNU tren azından çok baytlı karakterlerle çalışmıyor.

Ben kullanamadı ChrisDown en @ olarak pythonPOSIX karakter sınıflara arabirimleri yok.

Perl'i denedim, ancak UTF-8 dışındaki çok baytlı yerel ayarlar için 128 ile 255 arasındaki kod noktaları için sahte ve sistemin dönüşüm kitaplıklarını kullanmıyor.


Bunun etkili bir şekilde tek yol olduğunu düşünüyorum, ancak yasal kod noktaları aralığı hakkında karar vermek için ön bilgileri kullandığınız gerçeğinden başlayarak çeşitli sorunlardan muzdarip. Teoride en azından bir Unicode charmap kullanıyorsanız, karakter sınıfları komut dosyasından bağımsızdır (C yerel ayarlarına göre değil, Unicode standardına göre), ancak Unicode "genel kategorileri" de C karakter sınıflarıyla aynı değildir. BTW, combiningcombining_level3iswctype(i, wctype("combining"))
glibc'nin i18n ctypes'leri

@rici, düzenlemeye bakın (ve ayrıca sorunun).
Stéphane Chazelas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.