현재 로케일의 특정 문자 클래스에 있는 문자 목록을 검색하는 명령

현재 로케일의 특정 문자 클래스에 있는 문자 목록을 검색하는 명령

현재 로케일에서 주어진 문자 클래스(예 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, 두 번째 예에서는 단일 바이트), 동등한 유니코드 문자 코드 포인트 및 설명 측면에서 로케일의 문자 표현입니다.

문맥

(편집) 이제 취약점이 패치되고 공개된 지 오래되었으므로 약간의 맥락을 추가할 수 있습니다.

제가 조사할 때 그런 질문을 했는데요.CVE 2014-0475. glibc사용자가 LC_ALL=../../../../tmp/evil-locale표준 시스템 로케일 검색 경로를 기준으로 해결되는 로케일을 사용하여 모든 파일을 로케일 정의로 사용할 수 있다는 점에서 버그가 있었습니다.

악성 로케일을 만들 수 있습니다.s예를 들어 를 제외한 대부분의 문자 와 h일부 다른 문자가 고려되는 문자 집합당 단일 바이트를 사용합니다.공백일반적인 데비안 파일을 구문 분석하는 동안 bash실행 됩니다 ( 예를 들어 호스팅 서버 에서 셸 액세스를 얻는 데 사용할 수 있으며 서버 사용자 의 로그인 셸로 사용되며 서버가 / 변수를 허용 하고 공격자가 할 수 있음) 서버에 파일을 업로드합니다).sh/etc/bash.bashrcgitbashgitsshLC_*LANG

LC_CTYPE이제 에서 (컴파일된 로케일 정의) 를 발견한 경우 /tmp/evil그것이 불량한 것인지 어떻게 알 수 있습니까?

따라서 내 목표는 해당 로케일 정의를 컴파일 해제하고, 그렇지 않은 경우 적어도 주어진 문자 클래스에 어떤 문자(인코딩과 함께)가 있는지 아는 것입니다.

이를 염두에 두고:

  • 로케일(데비안의 로케일 정의와 같은 /usr/share/i18n/locale)에 대한 소스 파일을 살펴보는 솔루션은 제 경우에는 아무 소용이 없습니다.
  • 유니코드 문자 속성은 관련이 없습니다. 나는 로케일의 내용에만 관심이 있습니다. Debian 시스템에서는 두 개의 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호환 시스템의 경우 이는 환경 변수 중 비어 있지 않은 첫 번째 값에 따라 달라지며 LC_ALL, LC_CTYPE, LANG다음 명령을 통해 확인할 수 있습니다.locale charmap.

또한 주목할 만한 점 recodeAPI입니다:

명명된 프로그램은 recode단지 녹음 라이브러리의 응용 프로그램일 뿐입니다. 레코딩 라이브러리는 다른 C 프로그램에 대해 별도로 사용할 수 있습니다. 레코딩 라이브러리에 익숙해지는 좋은 방법은 recode프로그램 자체에 익숙해지는 것입니다.

설치된 레코딩 라이브러리를 사용하려면 C 프로그램에 다음 줄이 있어야 합니다.

#include <recode.h>

국제적으로 친화적인 문자열 비교를 위해 POSIXC표준은strcoll()기능:

함수 는 가 가리키는 문자열 과 가 가리키는 문자열을 strcoll()비교해야 하며 , 둘 다 현재 로케일의 LC_COLLATE 범주에 적절하게 해석됩니다.s1s2

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유니코드 문자 및 클래스의 경우 다음을 사용할 수 있습니다.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참맵 여부에 관계없이 다음을 사용합니다.아스키문자셋 외에는 아무것도 없습니다. 그래서 그것이 내가 얻는 전부입니다. 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함수는 도메인의 메시지 카탈로그에 대한 출력 문자 집합을 지정하는 데 사용할 수 있습니다. 도메인 이름. 그만큼코드세트인수는 유효해야 합니다.코드세트에 사용할 수 있는 이름iconv_open함수 또는 널 포인터.

만약코드세트매개변수는 널 포인터이며, bind_textdomain_codeset 현재 선택된 값을 반환합니다.코드세트이름이 있는 도메인의 경우 도메인 이름. 없으면 NULL을 반환합니다.코드세트아직 선택되지 않았습니다.

bind_textdomain_codeset기능은 여러 번 사용할 수 있습니다. 동일한 domainname 인수와 함께 여러 번 사용되는 경우 나중 호출이 이전 호출의 설정을 재정의합니다.

bind_textdomain_codeset함수는 선택한 코드 세트의 이름이 포함된 문자열에 대한 포인터를 반환합니다. 문자열은 함수 내부적으로 할당되며 사용자가 변경할 수 없습니다. 을 실행하는 동안 시스템이 코어에서 나가면 bind_textdomain_codeset반환 값은 NULL이고 전역 변수 errno가 그에 따라 설정됩니다.

네이티브를 사용할 수도 있습니다.유니코드 문자카테고리, 이는 언어 독립적이며 POSIX 클래스보다 우선합니다. 또는 전자를 호출하여 후자를 정의하는 데 충분한 정보를 제공할 수도 있습니다.

복잡성 외에도 유니코드는 새로운 가능성도 제공합니다. 하나는 각 유니코드 문자가 특정 문자에 속한다는 것입니다.범주."문자" 카테고리에 속하는 단일 문자를 와 일치시킬 수 있습니다 \p{L}. 해당 카테고리에 속하지 않는 단일 문자를 와 일치시킬 수 있습니다 \P{L}.

다시 말하지만, "문자"는 실제로 "유니코드 코드 포인트"를 의미합니다. \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 결코 일치하지 않습니다.

위의 정보를 제공한 동일한 웹사이트에서도 이에 대해 논의합니다.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컴파일할 수 있습니다 . 출력은 펑키하고 매우 유용하지 않습니다. 전혀 같지 않지만 위에서 지정한 대로 원시 형식을 얻을 수 있습니다.localesI18Ncharmaps

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유니코드와 관련이 없고 시스템 로캘에서 지원하는 모든 문자만 포함하는 불투명 유형이지만 실제로 유니코드를 지원하는 대부분의 시스템에서 값은 유니코드 코드 포인트에 해당합니다. 로케일 정의 자체는 유니코드를 기반으로 합니다.

유니코드는 알려진 모든 문자 집합의 상위 집합이므로 유니코드의 모든 유효한 코드 포인트(0 ~ 0xD7FF 및 0xE000 ~ 0x10FFFF)를 반복하면 최소한 지정된 문자 집합에서 지원하는 모든 문자가 나열되어야 합니다.

여기서는 시스템의 로케일 표준 API를 사용하여 어떤 유형이 특정 유형인지 확인하고 이를 로케일 인코딩의 인코딩된 형식으로 변환합니다. 우리는 주어진 유니코드 코드 포인트에서 이름을 얻기 위해서만 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비트) 바이트(여기서는 IDEOGRAPHIC SPACE의 경우 21 21)로 표현되는 상태로 전환됩니다. EUCJP에서는 동일한 바이트이지만상태 전환8번째 비트( )를 뒤집어서 A1 = 21 | 0x80더 무상태로 만듭니다.

이는 해당 상태 저장 인코딩에는 특정 문자를 작성하는 여러 가지 방법이 있음을 의미합니다(예를 들어 이러한 문자 중 여러 개를 삽입하는 방식).상태 전환시퀀스), 위 코드에 표시된 시퀀스는 그 중 하나일 뿐입니다(초기 기본 상태의 표준 시퀀스).

일반 로케일의 경우 문자는 0..0xD7FF, 0xE000..0x10FFFF 외부에 있을 수 없습니다.도적로케일, wchar_t가 지원하는 범위의 모든 문자가 가능합니다. 예를 들어 U+DCBA 또는 U+12345678 문자(또는 허용되는 경우 문자가 됨)가 있는 로캘을 만들 수 있습니다.공백. 그렇기 때문에 이를 포함하기 위해 해당 코드를 컴파일하려는 것입니다 -D SUPPORT_ROGUE_LOCALES. 하지만 이는 전체 목록을 스캔하는 데 훨씬 더 많은 시간이 걸린다는 것을 의미합니다.

recode@mikeserv의 솔루션은 자체 변환을 사용하고 더 이상 유지 관리되지 않으며 최대 0xFFFF까지의 유니코드 문자만 지원하고 GNU는 tr적어도 멀티바이트 문자에서는 작동하지 않으므로 사용할 수 없습니다 .

나는 사용할 수 없었다@ChrisDown의pythonPOSIX 문자 클래스에 대한 인터페이스가 없습니다 .

Perl을 사용해 보았지만 UTF-8 이외의 멀티바이트 로케일에 대한 128에서 255 사이의 코드 포인트는 가짜이며 시스템의 변환 라이브러리를 사용하지 않습니다.

관련 정보