現在のロケールで特定の文字クラスの文字のリストを取得するコマンド


18

何が指定された文字クラス内のすべての文字(のようなのリスト取得するための方法かもしれないblankalphadigit現在のロケールでは...)。

例えば、

LC_ALL=en_GB.UTF-8 that-command blank

理想的には、私のDebianシステムでは、次のようなものが表示されます。

      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

Cロケールでは、次のようなものを表示できます。

09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE

つまり、バイト配列(最初の例のUTF-8、2番目のシングルバイトなど)、同等のUnicode文字コードポイント、および説明に関するロケールの文字の表現。

環境

(編集)脆弱性は長い間パッチが適用され、公開されてきたので、少しコンテキストを追加できます。

私はCVE 2014-0475を調査していたときにその質問をしました。glibcユーザーLC_ALL=../../../../tmp/evil-localeが標準システムロケール検索パスに関連して解決されるようなロケールを使用できるようにするため、ロケール定義として任意のファイルを使用できるというバグがありました。

たとえば、文字セットごとに1バイトの不正なロケール作成できます。ここではshを除くほとんどの文字が空白と見なされ、典型的なDebian ファイルの解析中にbash実行されます(そして、たとえば、提供されているホスティングサーバーは、サーバーユーザーのログインシェルとして使用され、サーバーは/ 変数を受け入れ、攻撃者はサーバーにファイルをアップロードできます。sh/etc/bash.bashrcgitbashgitsshLC_*LANG

さて、でLC_CTYPE(コンパイル済みのロケール定義)/tmp/evilを見つけた場合、それがどのようにして不正なものであるかをどのようにして見つけるのでしょうか。

したがって、私の目標は、それらのロケール定義をアンコンパイルすることです。そうでない場合は、少なくとも、どの文字が(エンコードとともに)所定の文字クラスに含まれているかを把握します。

それを念頭に置いて:

  • ロケールのソースファイル(/usr/share/i18n/localeDebianのようなロケール定義)を調べるソリューションは、私の場合は役に立ちません。
  • Unicode文字のプロパティは関係ありません。ロケールが何を言っているかだけを気にします。Debianシステムでは、2つのUTF-8システムロケール間、さらには不正なロケール間でさえ、クラス内の文字のリストが異なる場合があります。
  • recodepythonまたはperlバイト/マルチバイトから/への文字変換を行うツールは、ロケールとは異なる方法で変換を実行する可能性があるため(実際には)、使用できません。

ほとんどのロケールでは、最終的には(glibcを使用した)LC_CTYPEに由来し/usr/share/i18n/locales/i18nます...もちろん、主にUnicode文字データベースに由来します。もちろん、コマンドを持っていいだろう
derobert

@derobert、はい、locale(少なくともGNUのものは)多くのカテゴリに保存されている多くの情報を取得しますが、LC_CTYPEとLC_COLLATEで最も重要な情報ではありません。その情報を取得したり、ロケール情報をコンパイルしたりするための隠しAPIがあるのだろうか。
ステファンシャゼル

ええ-あなたはその情報を解析することができます-私はついに編集をまとめました。おそらく既にインストールしたコマンドがいくつかあります-少なくとも私はしましたが、それらについても知りませんでした。役に立てば幸いです。具体的recodeuconvは、あなたがあなたが探しているとあなたが言うことをあなたに与えることができます。おそらくだけでも、luitod私は推測する...
mikeserv

それはとても良いです!つまりperl、まったく必要ないということです。
mikeserv

私は基本的にあなたがすでにそれを試したことがあるLC_CTYPEだけで基本的に文字セットを抽出することができるようですod -A n -t c <LC_CTYPE | tsortが、私はそれを聞いたことがありinfoませんでした。他にもありptxますが、関連性は低いと思います。とにかく、もしあなたがそれを試していない、そしてそうすることに決めたなら-公正な警告-それは少しの忍耐を必要とします。lehman.cuny.edu/cgi-bin/man-cgi?tsort+1
mikeserv

回答:


7

可能な最終ソリューション

だから私は以下の情報をすべて取り入れてこれを考え出しました:

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.

また、注目に値するのは、APIでrecodeあることです

指定されたプログラムrecodeは、その再コーディングライブラリの単なるアプリケーションです。記録ライブラリは、他のCプログラムで個別に利用できます。再コーディングライブラリにある程度精通する良い方法は、recodeプログラム自体に精通することです。

リコーディングライブラリをインストールしてから使用するには、Cプログラムに次の行が必要です。

#include <recode.h>

国際的にフレンドリな文字列比較のためにPOSIXC標準はstrcoll()関数を定義します:

strcoll()関数は、文字列により指さ比較しなければならないs1文字列にすることによって指さs2、両方の現在のロケールのLC_COLLATEカテゴリに適宜解釈されます。

strcoll()成功した場合、関数はerrnoの設定を変更してはなりません。

エラーを示す戻り値は予約されていないため、エラー状況を確認したいアプリケーションはerrnoを0に設定し、を呼び出してからerrnoを strcoll()確認する必要があります。

以下に、個別に配置された使用例を示します。

#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で提供されますが、英語の説明は利用できず、フランス語の説明がある場合は、代わりにLatin-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.

ただし、上記の方法には2つの大きな問題があります。まず、システムの照合順序があります-非ASCIIロケールの場合、文字セットのバイト値は単純に意味がありませんseq

さて、GNU tr's manページは、[:upper:] [:lower:]クラスを順番に拡張すると述べていますが、それほど多くはありません。

いくつかのsort手間のかかるソリューションを実装できると思いますが、それはバックエンドプログラミングAPIにとっては扱いにくいツールになるでしょう。

recodeこのことは正しく行われますが、あなたは先日プログラムにあまりにも恋をしているようには見えませんでした。たぶん、今日の編集は、より友好的な光を投じるかもしれません。

GNUはgettext関数ライブラリも提供しており、少なくともこのLC_MESSAGESコンテキストではこの問題対処できるようです。

-機能:char * bind_textdomain_codesetconst char *domainname, const char *codeset

このbind_textdomain_codeset関数を使用して、ドメインdomainnameのメッセージカタログの出力文字セットを指定できます 。コードセットの引数が有効でなければならないコードセットのために使用することができます名前iconv_open関数、またはNULLポインタ。

codesetパラメーターがNULLポインターの場合、domainnameという名前のドメインに対してbind_textdomain_codeset 現在選択されているコードセットを 返します。コードセットがまだ選択されていない場合は、NULLを返します。

このbind_textdomain_codeset関数は複数回使用できます。同じdomainname引数を使用して複数回使用すると、後の呼び出しで前の設定が上書きされます。

このbind_textdomain_codeset関数は、選択したコードセットの名前を含む文字列へのポインターを返します。文字列は関数内で内部的に割り当てられており、ユーザーが変更してはなりません。の実行中にシステムがコアから外れた場合、 bind_textdomain_codeset戻り値はNULLになり、それに応じてグローバル変数errnoが設定されます。

また、言語に依存せず、POSIXクラスをまったく使用しないネイティブUnicode文字カテゴリを使用するか、前者を呼び出して後者を定義するのに十分な情報を提供することもできます。

合併症に加えて、ユニコードは新しい可能性ももたらします。1つは、各Unicode文字が特定のカテゴリに属することです。「letter」カテゴリに属する​​単一の文字をと一致させることができます \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}*+ 0個以上のコードポイントと一致します。分音記号を含む文字に一致させるには、を使用します\p{L}\p{M}*+。この最後の正規表現àは、エンコード方法に関係なく常に一致します。所有量限定子は、バックトラックが\P{M}\p{M}*+、後続の結合マークなしで非マークと一致しないようにし\X ます。

上記の情報を提供したのと同じWebサイトでは、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)
...

... もっと

UTF-8サポートのないXTermsの仲介役となるluit端末UTF-8 pty翻訳デバイスもあります。変換されたすべてのバイトをファイルに記録したり-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私はそれらを機能させることはできないだろうということを十分に知っていることによって、私が物思いにふけってスクロールしたいくつかのものもあります。


1
これはすべて非常に便利で便利な情報ですが、ソースファイルに関する情報(i18n)は、現在使用しているロケールの生成に使用されている場合と使用されていない場合があります。ロケール情報は、おそらくから来ている/usr/lib/locale/locale-archive/some/dir/LC_CTYPE、それはだ、私のロケールに関連する部分、私は後だと、それらのファイルに保存されています。
ステファンシャゼル

@StephaneChezales- LC_STUFFアーカイブから抽出するだけでlocaledef-それも行います。デモもできると思います。あなたもいることとと、他のほとんどすべて見ることができstringsたりodまたは残りのいずれか。とにかくやった。しかし、ちなみに-はあなたcharmaps 現在使用しいるロケールです-そしてlocaledefそれについても報告します。それもrecodeそうです。
mikeserv

基本的には、システムのライブラリが文字クラス情報を照会するために手作業で行うことができると言っていますが、それを確実に行うには数千行のコードが必要になり、結果はシステム固有になります。(システムライブラリと同じ方法で環境を解析します(LOCPATH、LANG、LANGUAGE、LC_CTYPE ...、データの検索場所を特定し、抽出します...)。アーカイブからデータを抽出する方法がわかりません。しかしlocaledefを持つ。
ステファンChazelas

@StephaneChazelas-手作業で行うことはお勧めしません-コンピューターで行うことをお勧めします- od, recode、などのシステムバイナリを使用しますuconv。しかし、それは私の間違いでした-それlocaledefを抽出するのではなく、そうするのrecodeです。あなたはチェックアウトする必要がinfo recodeありrecodeます-そして、私が表示するテーブルコマンドに加えて、ほとんど同じことがあります-そして、それは同じように物事を処理すると思います。それはあなたの文字セットを薄い空気から引き抜くだけではありません。いずれにせよ、私はそれらのperlモジュールに大きな期待を持っていました-あなたは何か試してみましたか?
mikeserv

1
現在のロケールで特定の文字クラスの文字のリストを取得するAPIがあれば、それが具体的に私が探しているものです。これを行う方法を示すことができれば、答えを受け入れます。考えられる唯一のこと(および質問で「期待される出力」を取得した方法)は、iswblank(3)可能なすべての文字値に使用することです。
ステファンシャゼル

1

少なくともGNU、FreeBSD、またはSolarisシステムでは、このブルートフォースアプローチが機能します。

#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ごとにwchar_t、不透明な型であり、Unicodeとは関係がなく、システムのロケールでサポートされるすべての文字をカバーすることが保証されていますが、実際には、Unicodeをサポートするほとんどのシステムでは、値はUnicodeコードポイントに対応しますロケール定義自体はUnicodeに基づいています。

Unicodeはすべての既知の文字セットのスーパーセットであるため、Unicodeのすべての有効なコードポイント(0から0xD7FFおよび0xE000から0x10FFFF)をループするには、少なくとも特定の文字セットでサポートされるすべての文字をリストする必要があります。

ここでは、システムのロケール標準APIを使用して、指定されたタイプのものを確認し、ロケールのエンコーディングでエンコードされた形式に変換します。perlとそのcharnamesモジュールは、指定されたUnicodeコードポイントから名前を取得するためにのみ使用します。

ISO-2022-JPなどのステートフルエンコーディングを使用するロケールでは、エンコードされたフォームがデフォルトの初期状態から表示されるようにします。

ステートフル文字エンコーディングのロケールをインストールしたシステムは見つかりませんでしたが、少なくともGNUシステムでは、不正なロケールを作成できるようにいくつかを生成することができます(少なくともGNUツールはそれらで正しく動作しません)ロケール)。たとえば、通常のja_JPロケールでISO-2022-JPを使用するカスタムロケールでは、次のようになります。

$ 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

と比べて:

$ 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では、1B 24 42シーケンス(\e$B)はASCIIから文字が2(7ビット)バイト(ここではそのIDEOGRAPHIC SPACEの場合は21 21)として表現される状態に切り替わります。EUCJPでは同じバイトですが、状態の切り替えは8番目のビット(A1 = 21 | 0x80)を反転することで行われるため、よりステートレスになります。

つまり、これらのステートフルエンコーディングでは、特定の文字を記述する方法がいくつかあり(たとえば、いくつかの状態切り替えシーケンスを挿入する)、上記のコードで示されているシーケンスはそのうちの1つ(初期からの標準的なもの)デフォルト状態)。

通常のロケールの場合、文字は0..0xD7FF、0xE000..0x10FFFFの外にあることはできませんが、不正なロケールの場合、wchar_tでサポートされる範囲内の任意の文字を使用できます。たとえば、U + DCBAまたはU + 12345678文字(または許可されている場合は文字)が空白であるロケールを作成できます。そのため-D SUPPORT_ROGUE_LOCALES、それらをカバーするためにコードをコンパイルしたいのですが、それはリスト全体をスキャンするのにより多くの時間がかかることを意味します。

@mikeservのソリューションrecodeは独自の変換を使用するため使用できず、メンテナンスされなくなり、0xFFFFまでのUnicode文字のみをサポートします。GNU trは少なくともマルチバイト文字では動作しません。

私は使用できませんでしたChrisDownさん@としてpythonPOSIX文字クラスへのインタフェースを持っていません。

Perlを試しましたが、UTF-8以外のマルチバイトロケールの場合、128〜255のコードポイントは偽物であり、システムの変換ライブラリを使用しません。


これが効果的な唯一の方法だと思いますが、法的なコードポイントの範囲を決定するために事前知識を使用したという事実から始まるいくつかの問題に苦しんでいます。少なくとも理論的には、Unicode charmapを使用している場合、文字クラスはスクリプト(CロケールではなくUnicode標準による)に依存しませんが、Unicodeの「一般カテゴリ」もC文字クラスと同じではありません。:ところで、glibcの国際化のctypesのは、2つの文字クラスが含まcombiningcombining_level3(。すなわちiswctype(i, wctype("combining"))
RICI

@rici、編集(および質問)も参照してください。
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.