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


18

현재 로케일에서 지정된 문자 클래스 (예 blank: alpha,, digit...) 의 모든 문자 목록을 검색하는 방법은 무엇입니까?

예를 들어

LC_ALL=en_GB.UTF-8 that-command blank

이상적으로는 데비안 시스템에서 다음과 같이 표시됩니다.

      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.bashrc파일을 (그리고는에 쉘 액세스를 얻을하는 데 사용할 수 있습니다 git예를 들어 호스팅 서버 bashgit서버 사용자 의 로그인 쉘로 사용되며 ssh서버는 LC_*/ LANG변수를 허용 하고 공격자는 서버에 파일을 업로드 할 수 있습니다).

이제에서 LC_CTYPE(컴파일 된 로케일 정의)를 찾은 경우 /tmp/evil어떻게 그것이 불량한지 알 수 있습니다.

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

그래서 그것을 염두에두고 :

  • 로켈의 소스 파일을 보는 솔루션 ( /usr/share/i18n/localeDebian 의 것과 같은 로케일 정의 )은 필자의 경우 유용하지 않습니다.
  • 유니 코드 문자 속성은 관련이 없습니다. 나는 로케일의 말에만 관심이 있습니다. 데비안 시스템에서, 두 개의 UTF-8 시스템 로케일 사이에서도 악의적 인 로케일은 물론 클래스의 문자 목록이 다를 수 있습니다.
  • 도구처럼 recode, python또는 perl문자 변환에서 로케일과 다른 방식으로 변환을 (않으며 실제로)가 수도로 사용할 수 없습니다에 / 바이트 / 멀티 바이트를 할 수있다.

대부분의 로케일의 경우 궁극적으로 LC_CTYPE 항목 (glibc 포함) /usr/share/i18n/locales/i18n에서 가져옵니다 ... 물론 유니 코드 문자 데이터베이스에서 주로옵니다. 물론 명령을받는 것이 좋을 것입니다.
derobert

@derobert, 그렇습니다. locale(적어도 GNU는) 많은 범주에 저장된 많은 정보를 검색하지만 LC_CTYPE 및 LC_COLLATE에서 가장 중요하지 않은 정보를 검색합니다. 해당 정보를 검색하거나 로캘 정보를 컴파일 해제하는 숨겨진 API가 있는지 궁금합니다.
Stéphane Chazelas

예, 정보를 파싱 할 수 있습니다. 마지막으로 편집 내용을 정리했습니다. 아마도 이미 설치 한 몇 가지 명령이 있습니다. 적어도 내가 한 명령에 대해서는 몰랐습니다. 도움이 되길 바랍니다. 특히 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.

또한 주목할 가치 recode는 그것이 API 라는 것 입니다 .

명명 된 프로그램 recode은 단지 그 기록 라이브러리의 응용 프로그램입니다. 레코딩 라이브러리는 다른 C 프로그램에 대해 별도로 제공됩니다. 레코딩 라이브러리에 익숙해지기위한 좋은 방법은 recode프로그램 자체에 익숙해지는 것입니다.

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

#include <recode.h>

국제적으로 친숙한 문자열 비교를 위해 POSIXC표준은 strcoll()기능을 정의합니다 .

strcoll()함수는 현재 로케일의 LC_COLLATE 범주에 적절하게 해석 되는 s1로 표시된 문자열 과로 표시된 문자열을 비교해야합니다 s2.

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문자 클래스 와 관련하여 이미 CAPI를 사용 하여 문자 클래스 를 찾았 음을 언급했습니다 . 유니 코드 문자 및 클래스의 경우 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로 제공되지만 영어 설명은 사용할 수 없지만 프랑스어 설명은 라틴 -1을 사용하여 대신 프랑스어 설명이 제공됩니다. 그러나 LANGUAGEor 또는 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.

그러나 위의 방법에는 두 가지 주요 문제가 있습니다. 먼저 시스템의 조합 순서가 있습니다-비 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 함수 또는 널 포인터.

는 IF 코드 세트 매개 변수는 널 포인터, bind_textdomain_codeset 현재 선택된 반환 코드 세트 이름을 가진 도메인에 대한 도메인 이름을 . 코드 세트 가 아직 선택되지 않은 경우 NULL을 리턴합니다 .

bind_textdomain_codeset기능은 여러 번 사용할 수 있습니다. 동일한 domainname 인수와 함께 여러 번 사용될 경우, 나중에 호출하면 이전 호출에 의해 작성된 설정이 무시됩니다.

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

또한 언어에 독립적이며 POSIX 클래스를 완전히 포기하거나 후자를 정의하기에 충분한 정보를 제공하기 위해 전자를 호출 할 수있는 고유 유니 코드 문자 범주를 사용할 수도 있습니다 .

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

"문자"는 실제로 "유니 코드 코드 포인트"를 의미합니다. \p{L}"letter"범주의 단일 코드 포인트와 일치합니다. 입력 문자열이로 à 인코딩 된 경우 악센트없이 U+0061 U+0300일치 a합니다. 입력이로 à인코딩 되면 악센트와 U+00E0일치 à합니다. 그 이유는 코드 포인트 U+0061 (a)U+00E0 (à)카테고리가 모두 "letter" U+0300에 있고 카테고리는 "mark"에 있기 때문입니다.

이제 \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에서 "ko 페이지" 예를 들어, 그리고 어느 정도는 또 다른 진짜 큰 문제는 그들이 모든 점유율을 보인다 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-8 ptyI는 이동 사이 xterms을위한없이 UTF-8을 지원 역할을 추측 변환 장치. 변환 된 모든 바이트를 파일 또는 -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 모듈을 호출하는 것이 나보다 조금 덜 어려울 것입니다. 다시 말하지만, 이들은 이미 내 컴퓨터에 있었고 펄도 사용하지 않습니다. 또한 I18N내가 잘 작동하지 않으면 서두르지 않고 스크롤 한 몇 가지 가 있습니다.


1
그것은 매우 훌륭하고 유용한 정보이지만, i18n현재 사용중인 로케일을 생성하는 데 사용되거나 사용되지 않은 소스 파일에 대한 정보를 제공합니다 . 로케일 정보는 아마도 /usr/lib/locale/locale-archive또는 /some/dir/LC_CTYPE에서 오는 것일 수 있으며 , 이 파일은 내가 찾은 파일에 저장된 로케일과 관련이 있습니다.
Stéphane Chazelas

@StephaneChezales- LC_STUFF아카이브에서 압축을 풀면 localedef됩니다. 데모도 할 수 있습니다. 당신은 또한 그 strings또는 다른 것들과 함께 또는 거의 모든 것을 볼 수 있습니다 od. 어쨌든 했어요 그러나 방법에 의해 -가 charmaps 있습니다 와 - 로케일 개봉 현재 사용하고 localedef그뿐만 아니라에보고합니다. 또한 그 recode일도 마찬가지입니다.
mikeserv

기본적으로 시스템 라이브러리가 문자 클래스 정보를 쿼리하기 위해 수행 할 수있는 작업을 직접 수행 할 수 있지만, 안정적으로 수행하려면 수천 줄의 코드가 필요하며 결과는 시스템에 따라 다릅니다. (시스템 라이브러리와 동일한 방식으로 환경을 구문 분석합니다 (LOCPATH, LANG, LANGUAGE, LC_CTYPE ..., 데이터를 찾을 위치를 식별하고 추출하는 중 ...). 아카이브에서 항목을 추출하는 방법을 볼 수 없습니다. localdef를 생각과 함께.
스테판 Chazelas가

@StephaneChazelas - 나는 당신이 손으로 그것을하지 않는 것이 좋습니다 - 시스템과 같은 바이너리를 사용하여 - 당신이 컴퓨터와 함께 할 제안 od, recode, uconv그리고 나머지는. 그러나 그것은 내 실수였습니다. localedef추출하는 것이 아니라 recode그 것입니다. 당신은 체크 아웃해야 info recode합니다. recode테이블 명령 외에도 거의 같은 것이 있습니다. 그리고 그것은 같은 방식으로 일을 처리 할 것이라고 생각합니다. 단순히 얇은 공기에서 캐릭터 셋을 꺼내는 것이 아닙니다. 어쨌든 나는 그 perl모듈에 대한 기대가 높았 습니다.
mikeserv

1
현재 로케일의 주어진 문자 클래스에서 문자 목록을 검색하는 API가 있다면, 그것은 내가 찾고있는 것입니다. 이 작업을 수행하는 방법을 보여줄 수 있다면 대답을 받아들입니다. 내가 생각할 수있는 유일한 것은 (그리고 내 질문에서 "예상 결과"를 얻는 방법) iswblank(3)가능한 모든 문자 값에 사용하는 것입니다.
Stéphane Chazelas

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

유니 코드는 알려진 모든 문자 세트의 수퍼 세트이므로 유니 코드의 모든 유효한 코드 포인트 (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의 @ 으로 python는 POSIX 문자 클래스에 대한 인터페이스가 없습니다.

Perl을 시도했지만 UTF-8 이외의 다중 바이트 로케일의 경우 128에서 255 사이의 코드 포인트는 가짜이며 시스템의 변환 라이브러리를 사용하지 않습니다.


나는 이것이 효과적으로 할 수있는 유일한 방법이라고 생각하지만, 법률 지식의 범위를 결정하기 위해 사전 지식을 사용했기 때문에 몇 가지 문제가 발생합니다. 이론적으로 적어도 유니 코드 Charap을 사용하는 경우 문자 클래스는 스크립트와 독립적이지만 (C 로캘이 아닌 유니 코드 표준에 따름) 유니 코드 "일반 범주"는 C 문자 클래스와 동일하지 않습니다. : BTW,의 glibc의 국제화 (i18n)하는 ctypes가 두 개 더 문자 클래스 포함 combining하고 combining_level3. (즉 iswctype(i, wctype("combining")))
RICI

@rici, 편집 (및 질문)을 참조하십시오.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.