
現在のロケールで特定の文字クラス(たとえば、blank
...)alpha
のすべての文字のリストを取得する方法はありますか?digit
例えば、
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文字コードポイント、および説明で表されます。
コンテキスト
(編集)脆弱性がパッチされ公開されてから古いので、いくつかの背景情報を追加できます。
調査中にこんな質問をしました。CVE2014-0475。ユーザーが標準のシステムロケール検索パスに基づいて検証されたロケールをglibc
使用して、すべてのファイルをロケール定義として使用できるようにするバグがあります。LC_ALL=../../../../tmp/evil-locale
不良ロケールを作成できます。s
たとえば、他のh
文字以外のほとんどの文字が考慮される1文字あたり1バイトの文字セットです。スペースこれは通常のDebianファイルを解析するときに実行されますbash
(ホストサーバーからシェルアクセスを取得するために使用できます。たとえば、サーバーユーザーとしてログインシェルを提供し、サーバーは/変数を受け入れ、攻撃者はファイルをサーバー)。sh
/etc/bash.bashrc
git
bash
git
ssh
LC_*
LANG
ではLC_CTYPE
、1つ(コンパイルされたロケール定義)を見つけると、/tmp/evil
それが間違った定義であるかどうかを見つけることができ、どのようにそれを見つけることができますか?
したがって、私の目標は、これらのロケール定義をコンパイル解除し、そうでない場合は、少なくとも指定された文字クラスの文字(および対応するエンコード)を知ることです。
したがって、次の点を考慮してください。
- 私の場合、ロケールソースファイル(
/usr/share/i18n/locale
Debianのロケールなどのロケール定義)を表示するソリューションは機能しませんでした。 - Unicode文字属性は関係ありません。私はロケールの内容だけに興味があります。 Debianシステムでは、クラスの文字リストが2つのUTF-8システムロケール(不良システムロケールはもちろん)間で異なる場合があります。
recode
、同じツールpython
はバイト/マルチバイトから文字への変換を実行し、実際にはロケールとは異なる方法で変換できるため使用できません。perl
答え1
可能な最終ソリューション
だから私は次のすべての情報を収集し、次の結論に達しました。
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互換性のあるシステムは、環境変数のnullではなく最初の値に依存します。LC_ALL, LC_CTYPE, LANG
これはコマンドで確認できます。locale charmap.
また注目すべきrecode
点はAPIです:
これは
recode
録音ライブラリの1つのアプリケーションです。記録ライブラリは、他のCプログラムとは独立して使用できます。録音ライブラリに慣れるのに良い方法は、プログラムrecode
自体に慣れることです。インストール後に記録ライブラリを使用するには、Cプログラムに次の1行が必要です。
#include <recode.h>
国際に優しい文字列比較POSIX
とC
標準定義strcoll()
機能:
この関数は、
strcoll()
指す文字列と指す文字列をs1
比較する必要がありs2
、両方とも現在のロケールのLC_COLLATEカテゴリに適切に解釈されます。成功した場合、この
strcoll()
関数はerrno設定を変更しないでください。エラーを示す戻り値は保持されないため、エラー条件を確認したいアプリケーションはerrnoを0に設定して呼び出してから
strcoll()
errnoを確認する必要があります。
ここに一つあります。それぞれに位置使用法の例:
#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);
}
キャラクタークラスについては、APIを使ってPOSIX
探してC
いることをすでに知っていました。 Unicode文字とクラスの場合は、次のものを使用できます。recode's
ダンプ名目的の出力を取得するための文字セットです。それから手動で再度:
たとえば、このコマンドは
recode l2..full < input
次から始まるという意味です。ラテン語2到着UCS-2、〜のようにダンプ名次のリンクのみUCS-2。この場合、元のrecode
コンテンツは表示されません。 ラテン語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
本当にを選択すると、両方の説明が利用可能になると、リストの優先順位がフランス語に変わります。
上記のような構文を使用して組み合わせます。テストデータセットが含まれています。次の方法で独自のキャラクターマップを取得できます。
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文字表の有無にかかわらず使用ASCIIコード文字セットはそれ以上です。それが私が持っているすべてです。フィルタリングせずに実行するとluit
ロールバックod
され、同じマップが再印刷されます。\0400.
しかし、上記のアプローチには2つの主な問題があります。最初のものはシステムの組み合わせ順序です。 ASCII以外のロケールの場合、文字セットのビット値は重要ではありませんseq
。これが解決しようとする問題の核心であると考えるからです。
さて、GNUtr's man
ページにはクラスを順番に拡張することが示されていますが、[:upper:]
[:lower:]
これはあまりありません。
いくつかの果敢なソリューションを使用すると達成できると思いますsort
が、バックエンドプログラミングAPIにはやや差し迫ったツールになります。
recode
ちゃんとしたけど、前回は番組が気に入らなかったようでした。おそらく、今日の編集のために、より親しみやすいように見えるかもしれません。
GNUはまた、gettext
次のことができると思われる関数ライブラリも提供します。この問題を解決する少なくともLC_MESSAGES
文脈上:
- 機能:
char * bind_textdomain_codeset
(const char *domainname, const char *codeset
)この
bind_textdomain_codeset
関数は、ドメイン・メッセージ・カタログの出力文字セットを指定するために使用できます。 ドメイン名。これコードセットパラメーターは有効でなければなりません。コードセット利用可能な名前iconv_open関数またはヌルポインタ。もしコードセットパラメータはNULLポインタで、
bind_textdomain_codeset
現在選択されている値を返します。コードセット名前のあるドメインの場合 ドメイン名。それ以外の場合はNULLを返しますコードセットまだ選択されていません。この
bind_textdomain_codeset
機能は複数回使用できます。同じドメイン名パラメータが複数回使用されると、後続の呼び出しは前の呼び出しの設定を上書きします。この
bind_textdomain_codeset
関数は、選択したコードセットの名前を含む文字列へのポインタを返します。この文字列は関数の内部に割り当てられ、ユーザーが変更することはできません。システムが実行中にコアを終了すると、bind_textdomain_codeset
戻り値はNULLで、グローバル変数errnoがそれに応じて設定されます。
このマシンを使用することもできます。Unicode 文字カテゴリー、これらは言語に依存せず、POSIXクラスを完全に放棄するか、前者が後者を定義するのに十分な情報を提供する必要があります。
複雑さに加えて、Unicodeは新しい可能性も提供します。 1つは、各Unicode文字が特定の文字に属することです。カテゴリー。「文字」カテゴリに属する個々の文字を一致させることができます
\p{L}
。そのカテゴリに属さない個々の文字を一致させることができます\P{L}
。繰り返しますが、「文字」は実際には「Unicodeコードポイント」を意味します。
\p{L}
「文字」カテゴリの単一のコードポイントと一致します。入力文字列à
がエンコードされている場合は、アクセントなしでU+0061 U+0300
一致します。a
入力à
がエンコードされると、U+00E0
アクセントと一致します。à
その理由は、コードポイントU+0061 (a)
とがU+00E0 (à)
両方とも「文字」カテゴリに属し、「タグ」U+0300
は「表示」カテゴリに属するためです。これで、タグを結合するゼロ以上のコードポイントと一致している間にタグを結合しない.matchesコードポイント
\P{M}\p{M}*+
と同等の理由を理解する必要があります。発音区別記号を含む文字を一致させるには、を使用します。最後の正規表現は、エンコード方法に関係なく常に一致します。所有数量子は、逆追跡により、後続の結合トークンなしで非トークンと一致する結果が発生しないことを保証します。\X
\P{M}
\p{M}*+
\p{L}\p{M}*+
à
\P{M}\p{M}*+
\X
上記の情報を提供する同じウェブサイトでもこれについて議論します。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
は、私もスクロールできないことをよく知っているので、スクロールしたいということです。
答え2
少なくとも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を使用して、どのタイプが特定のタイプに属しているかを確認し、それをロケールエンコーディングのエンコーディングに変換します。我々は、与えられたUnicodeコードポイントから名前を取得するために対応するperl
モジュールを使用します。charnames
ステートフルエンコード(ISO-2022-JPなど)を使用するロケールでは、エンコード形式がデフォルトの初期状態で表示されることを確認します。
ステートフルな文字エンコーディングがインストールされたロケールを持つシステムが見つかりませんでしたが、少なくともGNUシステムでは、悪意のあるロケールが作成されるようにいくつかのロケールを生成することが可能です(少なくともGNUツールはシステムで正しく機能しません)。これらのシステム)ロケール)。たとえば、ISO-2022-JPと一般的なロケールを使用するja_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ビット)バイトで表示される状態に切り替わります(21 21はこの表の文字スペースを表します)。 EUCJPではバイトは同じですが状態遷移これはビット8()を反転することによって行われA1 = 21 | 0x80
、これは状態を維持しません。
これは、これらのステートフルエンコーディングには特定の文字を作成するためのさまざまな方法があることを意味します(たとえば、複数の文字を挿入するなど)。状態遷移シーケンス)、上記のコードに示されているシーケンスはそのうちの1つにすぎません(初期基本状態の標準シーケンス)。
一般言語環境では、文字は0..0xD7FF、0xE000..0x10FFFFの範囲を超えることはできません。盗賊ロケールでは、wchar_t がサポートする範囲内の任意の文字が可能です。たとえば、U + DCBAまたはU + 12345678文字(または許可されている場合はその文字)でロケールを作成できます。スペース。-D SUPPORT_ROGUE_LOCALES
これがリスト全体をスキャンするのにさらに時間がかかることを意味していますが、それを処理するためにコードをコンパイルする理由です。
recode
@mikeservのソリューションは自己変換を使用し、メンテナンスされなくなり、最大0xFFFFのUnicode文字のみをサポートし、GNUはtr
少なくともマルチバイト文字をサポートしていないため使用できません。
利用できません@christangのPOSIX文字クラスへのインタフェースはpython
ありません。
私はPerlを試しましたが、UTF-8以外のマルチバイトロケールは128から255のコードポイントにも同様に適用され、システムの変換ライブラリを使用しません。