可能な最終ソリューション
だから私は以下の情報をすべて取り入れてこれを考え出しました:
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>
国際的にフレンドリな文字列比較のためにPOSIX
とC
標準は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_codeset
(const 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
私はそれらを機能させることはできないだろうということを十分に知っていることによって、私が物思いにふけってスクロールしたいくつかのものもあります。
/usr/share/i18n/locales/i18n
ます...もちろん、主にUnicode文字データベースに由来します。もちろん、コマンドを持っていいだろう