在目前語言環境中檢索給定字元類中的字元列表的命令
有什麼方法可以在目前語言環境中檢索給定字元類(如,…)中的所有字元
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,第二個範例中的單字節)、等效的 Unicode 字元程式碼點和描述。
語境
(編輯)既然漏洞早已被修補和披露,我可以添加一些上下文。
我在調查CVE 2014-0475時問了這個問題。
glibc
有一個錯誤,它允許使用者使用LC_ALL=../../../../tmp/evil-locale
相對於標準系統區域設置搜尋路徑解析的區域設置,因此允許使用任何文件作為區域設置定義。我可以創建一個流氓語言環境,例如每個字元字元集一個字節,其中大多數字元除了
s
,h
還有一些其他字元被認為是空白,這將在解析典型的 Debian文件時bash
執行(並且可以用來在例如,提供的託管伺服器用作伺服器使用者的登錄 shell,伺服器接受/變數,攻擊者可以將文件上傳到伺服器)。sh``/etc/bash.bashrc``git``bash``git``ssh``LC_*``LANG
現在,如果我在 中找到
LC_CTYPE
(編譯的語言環境定義)/tmp/evil
,我將如何發現它是一個流氓,以及以何種方式。所以我的目標是取消編譯那些語言環境定義,如果沒有,至少知道哪個字元(連同它們的編碼)在給定的字元類中。
所以考慮到這一點:
- 在我的情況下,查看語言環境源文件的解決方案(如 Debian 中的語言環境定義
/usr/share/i18n/locale
)是沒有用的。- Unicode 字元屬性無關緊要。我只關心語言環境的內容。在 Debian 系統上,即使在兩個 UTF-8 系統語言環境之間,更不用說流氓語言環境,一個類中的字元列表也可能不同。
- 不能使用像
recode
,python
或perl
進行字節/多字節到/從字元轉換的工具,因為它們可能(實際上確實如此)以與語言環境不同的方式進行轉換。
至少在 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 工具在那些環境中無法正常工作)語言環境)。例如,對於使用 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 表示 IDEOGRAPHIC SPACE)。在 EUCJP 中,它是相同的字節,但狀態切換是通過翻轉第 8 位 (A1 = 21 | 0x80
) 來完成的,這使其更加無狀態。這意味著在那些有狀態的編碼中,有幾種方法可以寫入給定的字元(例如,通過插入幾個狀態切換序列),上面程式碼顯示的序列只是其中之一(最初的規範序列)預設狀態)。
雖然對於普通語言環境,字元不能超出 0..0xD7FF、0xE000..0x10FFFF,但對於流氓語言環境,wchar_t 支持的範圍內的任何字元都可以。例如,我可以創建一個語言環境,其中 U+DCBA 或 U+12345678 個字元(或者如果允許它們是字元)是空白的。這就是為什麼您要編譯該程式碼
-D SUPPORT_ROGUE_LOCALES
以覆蓋這些程式碼,儘管這意味著掃描整個列表需要更多時間。我不能使用@mikeserv 的解決方案,因為
recode
它使用了它自己的轉換,不再維護並且只支持最高 0xFFFF 的 Unicode 字元,並且 GNUtr
至少不能處理多字節字元。我不能使用@ChrisDown,因為
python
它沒有到 POSIX 字元類的介面。我嘗試過 Perl,但對於 UTF-8 以外的多字節語言環境,128 到 255 之間的程式碼點是虛假的,並且不使用系統的轉換庫。
可能的最終解決方案
所以我已經收集了以下所有資訊並提出了這個:
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.
另外值得注意
recode
的是它是一個 api:命名的程序
recode
只是其重新編碼庫的一個應用程序。重新編碼庫可單獨用於其他 C 程序。熟悉重新編碼庫的一個好方法是熟悉recode
程序本身。要在安裝後使用重新編碼庫,C 程序需要有一行:
#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); }
關於
POSIX
字元類,您已經註意到您使用C
API 來查找它們。對於 unicode 字元和類,您可以使用recode's
dump-with-names字元集來獲得所需的輸出。再次從其手冊中:例如,該命令
recode l2..full < input
意味著從Latin-2到UCS-2 的必要轉換,因為dump-with-names僅從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
orLANG
環境變數以字母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字元映射,都使用ASCII字元集,僅此而已。所以這就是我所得到的。如果我在不
luit
過濾的情況下執行它,od
會將它回滾並再次列印相同的地圖\0400.
但是,上述方法存在兩個主要問題。首先是系統的整理順序——對於非 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函式的有效程式碼集名稱,或者是空指針。如果codeset參數是空指針,則返回名稱為domainname的域
bind_textdomain_codeset
的目前選定程式碼集。如果尚未選擇任何程式碼集,則返回 NULL。該
bind_textdomain_codeset
功能可以多次使用。如果多次使用同一個域名參數,後面的呼叫會覆蓋前面的設置。該
bind_textdomain_codeset
函式返回一個指向包含所選程式碼集名稱的字元串的指針。該字元串在函式內部分配,使用者不得更改。如果在執行過程中系統退出核心bind_textdomain_codeset
,則返回值為 NULL,並相應地設置全域變數 errno。您也可以使用本機Unicode 字元類別,它們與語言無關並且完全放棄 POSIX 類,或者可能呼叫前者為您提供足夠的資訊來定義後者。
除了複雜性之外,Unicode 還帶來了新的可能性。一個是每個 Unicode 字元都屬於某個*類別。*您可以將屬於“字母”類別的單個字元與
\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}*+
匹配零個或多個組合標記的程式碼點。要匹配包含任何變音符號的字母,請使用\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) ...
… 和更多
還有一個
luit
終端 UTF-8pty
翻譯設備,我猜它是不支持 UTF-8 的 XTerms 的中間人。它處理很多開關——例如將所有轉換的字節記錄到文件中或-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
,我很清楚我不會讓它們工作,因此我若有所思地滾動。