[출처 : http://blog.naver.com/nlp1/150079485722]


 한글

 구분  시작  끝
 한글(자음, 모음)  1100  11FF
 호환용 한글(자음, 모음)  3131  318F
 한글 음절(가~힣)  AC00  D7A3

 

한자

 구분  시작  끝
 한중일 부수 보충  2E80  2EFF
 한중일 통합 한자 확장 - A  3400  4DBF
 한중일 통합 한자  4E00  9FBF
 한중일 호환용 한자  F900  FAFF
 한중일 통합 한자 확장  20000  2A6DF
 한중일 호환용 한자 보충  2F800  2FA1F

 

일어

 구분  시작  끝
 하라가나  3040  309F
 가타카나  30A0  30FF
 가타카나 음성 확장  31F0  31FF
[출처 : http://bbs.python.or.kr/viewtopic.php?p=66561&sid=d7caa9e552c40cae5c64bd0169a5d73a]

>>> a = "\uc5ec\ub7ec" 
>>> a.decode('unicode-escape') 
u'\uc5ec\ub7ec' 
>>> print a.decode('unicode-escape') 
여러 



>>> import re 
>>> re.sub(r'\\u(\w+)', lambda m: unichr(int(m.group(1), 16)), a) 
u'\uc5ec\ub7ec' 
>>> print _ 
여러  
[출처 : http://lumitech.tistory.com/entry/Python-String-Unicode-translate-function]


문자(열) 교체 함수 str.translate(), unicode.translate() 사용법

우선 일반 문자열(unicode object 아닌 문자열)부터.

str.translate(tbl,del)두개의 인자를 받는다. tbl은 0~255의 ASCII문자를 각각 대체할 문자로 만든 매핑테이블이다. 말이 테이블이지 길이 256짜리 문자열이다. 즉, ASCII코드 32인 문자(스페이스)는 매핑테이블의 32번째 글자로 바꿔주는 것이다. 따라서 tbl은 꼭 길이 256인 문자열(str object)여야 한다.

string.translate(s, tbl, del) == s.translate(tbl, del) 이다.

 

바로 예제 ㄱㄱㅅ

 

  1. #원본 문자열. \n는 개행, \t는 탭문자, \b는 앞글자를 지운다.
    tstr = """가나다\n\t\b123 4\b5\b6\babcd efgh (789) -_-+ 라마바 사2사2 文字"""

    # 원본 문자열을 프린트
    print "original:", tstr

    # 간단한 translate. 각 바이트의 첫 비트로 translate
    tbl = ""
    for cc in range(256):
       if cc < 128: tbl += "0"
       else: tbl += "1"
    print "tbl =", tbl
    print "initial bit:", tstr.translate(tbl)

 

컨트롤 캐릭터를 지우는데 활용해 보기.

 

  1. # ascii code값이 32미만(컨트롤캐릭터)이면 32(space)로 바꾸는 매핑테이블. \n \r \t \b 이런거 다 공백으로 바뀐다.
    TRMAP_ASCII_CTRL2SPACE = "".join([chr(max(32,cc)) for cc in range(256)])
    print "ctrl to space:", tstr.translate(TRMAP_ASCII_CTRL2SPACE)

    # 컨트롤 캐릭터를 공백으로 바꾸고 홀수는 지우는 변환.
    print "ctrl to space deleting '13579':", tstr.translate(TRMAP_ASCII_CTRL2SPACE, "13579")

 

컨트롤 캐릭터를 공백으로 바꾸지 않고 del인자를 써서 삭제할 수도 있다.

  1. # 아무것도 바꾸지 않는 매핑 테이블
    TRMAP_NOCHANGE = "".join([chr(cc) for cc in range(256)])

    # 컨트롤 캐릭터만 삭제
    ASCII_CTRLCHARS = "".join([chr(cc) for cc in range(32)])
    print "delete ctrl chars:", tstr.translate(TRMAP_NOCHANGE, ASCII_CTRLCHARS)

 

character code가 127이하인 문자를 삭제하는 del인자를 써서 한글, 한자, 일어 등 멀티바이트문자만 남길 수도 있다. 간단하므로 예제 코드 생략.

 

다음은 unicode.translate()

이건 사용법은 비슷하지만 두가지 차이점이 있다. 첫째, 매핑 테이블은 진짜-_-테이블이라는것. 둘째, del 인자를 주지 않는다는 것.

매핑테이블은 dict로 정의한다. 그래서 메모리를 크게 잡아먹을 수도 있다. 그래도 함수 수행자체는 뎁따 빠르므로 활용가치가 높다.

매핑 테이블을 만드는 유용한 함수를 하나 같이 소개한다.

__builtins__.zip(seq1, seq2, ... ) 함수는 리스트를 반환하는데, seq1, seq2, ... 에서 순서대로 하나씩 꺼내서 tuple로 묶은 리스트를 반환한다.

즉, zip([1,2,3], ('a', 'b', 'c')) 는 [(1,'a'), (2,'b'), (3,'c')] 를 리턴한다.

dict object는 zip의 결과를 초기화 인수로 받을 수 있도록 만들어져 있으므로, 이걸 활용하면 unicode translate 맵핑테이블을 쉽게 작성할 수 있다.

 

한글이 나타나는 unicode range가 정해져 있으므로, 한글을 공백으로 바꿔버리는 예제를 만들어 보자.

  1. # 위에서 사용한 테스트 문자열을 unicode로 바꾼다.
    utstr = unicode(tstr, "utf8")

    # unicode에서 한글이 나타나는 영역이다.
    __unicode_range_hangul = range(0xac00, 0xd7a4)
    __unicode_range_hangul_jamo1 = range(0x1100, 0x11fa)
    __unicode_range_hangul_jamo2 = range(0x3131, 0x318f)
    __unicode_range_korean = __unicode_range_hangul + __unicode_range_hangul_jamo1 + __unicode_range_hangul_jamo2

    __build_mapping_range2char = lambda r,uc: zip(r, uc * len(r)) 

    # 한글을 모두 공백으로 바꿔버리는 매핑테이블
    trmap_korean = dict(__build_mapping_range2char(__unicode_range_korean, u" "))

    print "utstr:", utstr
    print "utstr without Korean chars:", utstr.translate(trmap_korean)

 

삭제를 하려면 매핑 테이블에서 빈 문자열( u"" )을 주면 된다. __build_mapping_range2char() 람다함수를 조금 고치면 된다. 예제 생략.

[출처 : http://mygony.com/archives/1110]


utf-8 한글을 자르기 위한 함수입니다. javascript 처럼 멀티바이트 글자에 대해 1문자로 취급할 수도 있도록 했습니다. 원래대로라면 utf-8 으로 된 한글은 3byte 이지만, 익숙한 계산법을 따르기 위해서 이 함수에서는 2byte인 것처럼 취급합니다. 즉, 다음과 같습니다.

원본
한글과 English를 혼용해서 씁니다.
checkmb=true, len=10
한글과 Eng (한글=2*3 + 공백=1*1 + 영문=1*1 => 10)

checkmb=false, len=10
한글과 Englis (모두 합쳐 10자)

 $a = '한글hangul도 포함include되었습니다.';

 
/**
* cut string in utf-8
* @author gony (http://mygony.com)
* @param $str     source string
* @param $len     cut length
* @param $checkmb if this argument is true, the function treats multibyte character as two bytes. default value is false.
* @param $tail    abbreviation symbol
* @return string  processed string
*/
function strcut_utf8($str, $len, $checkmb=false, $tail='...') {
    preg_match_all('/[\xEA-\xED][\x80-\xFF]{2}|./', $str, $match);
 
    $m    = $match[0];
    $slen = strlen($str);  // length of source string
    $tlen = strlen($tail); // length of tail string
    $mlen = count($m); // length of matched characters
 
    if ($slen <= $len) return $str;
    if (!$checkmb && $mlen <= $len) return $str;
 
    $ret   = array();
    $count = 0;
 
    for ($i=0; $i < $len; $i++) {
        $count += ($checkmb && strlen($m[$i]) > 1)?2:1;
 
        if ($count + $tlen > $len) break;
        $ret[] = $m[$i];
    }
 
    return join('', $ret).$tail;
}


파라미터 설명 
String $str : 원본 문자열
Integer $len : 문자열을 자를 길이
Boolean $checkmb : 이 값을 true로 하면 한글을 영문2자와 같이 취급한다. 기본값은 false
String $tail : 생략후 붙일 줄임 기호

반환값
{String} 처리된 문자열

주의! 이 함수는 UTF-8 문자열을 다룹니다. 다른 charset 에는 적용되지 않습니다.

mb_ 계열 함수가 없는 환경을 위해서 만들어봤습니다.

거의 없을 줄 알았는데 아직도 그런 환경이 있기는 있더라구요. ^^;; 
[출처 : http://www.ezslookingaround.com/blog/tech/?no=636]


 1. 파일 매칭과 정규식을 혼동하지 말자 


    우선 주의해야 할 것이 있어 먼저 말해 둡니다. 
    Shell이 파일 패턴 매칭에 쓰는 와일드카드(wildcard)와 정규식을 혼동해서는 안됩니다. 
    또한 와일드 카드와 정규식은 공통적으로 다음과 같은 문자들을 특별하게 취급합니다: 
    `*'와 `?', `()', `[]', `|'. 


    Shell과 find, cpio와 같은 프로그램들은 정규식이 아닌 파일 패턴 매칭을 위해 와일드카드 
    문자를 쓴다는 것을 먼저 기억해 두어야 합니다. 

    또한 이러한 특수문자들은 shell에 의해 확장되어 버리기 때문에 미리 따옴표로 둘러싸야 합니다. 
    아래의 명령을 입력하면: 

    $ grep [A-Z]*.c chap[12]

    Shell은 다음과 같이 확장할 것입니다: 

    grep Array.c Bug.c Comp.c chap1 chap2

    가장 간단한 방법은 의심스러운 부분은 모두 작은 따옴표인 `''으로 둘러싸는 것입니다. 


2. Using M-etacharacters in Regular Expression 



    정규식을 쓸 때에는 다음 세가지를 고려해야 합니다: 

        1) Anchor는 텍스트 한 줄에서 패턴이 위치하는 곳을 지정하며, 
        2) Character들은 그 위치에서 하나 이상의 문자에 매치(match)되며, 
        3) Modifier는 앞에 나온 문자 집합의 반복 횟수를 지정합니다. 



    Caret (^) 문자는 줄의 첫 부분이라는 것을 나타내는 anchor이며, 
    hash mark (#)는 단순히 문자 자체를 의미합니다. 
    Asterisk (*)는 modifier이며, 이 의미는 앞에 나온 문자 집합이 0개 이상 있다는 뜻입니다. 
    1개 이상이 아닌 0개 이상인 것에 주의하기 바랍니다. 



    정규식은 크게 단순 정규식1과 확장 정규식2으로 나눌 수 있습니다. 
    awk, egrep과 같은 몇몇의 프로그램은 확장 정규식을 지원하며, 
    나머지 대부분의 프로그램은 단순 정규식 표현만 지원합니다. 
    이 프로그램들에는 vi, sed, grep, csplit, dbx, more, ed, expr, lex등이 있습니다. 


3. Anchors 



    패턴의 위치를 지정하는 anchor에는 ^와 $가 있습니다. 
    전자는 start anchor라고 하며, 후자는 end anchor라고 합니다. 
    각각은 텍스트 한 줄에서 첫 부분, 끝 부분을 의미합니다. 
    따라서 정규식 "^A''는 문자 'A'이되, 문장의 처음에 나오는 'A'를 의미합니다. 
    마찬가지로 "$A''는 문자 'A'이되, 문장의 마지막에 나오는 'A'만을 의미합니다. 


    두 anchor 모두 제 위치에 있을 때에만 그 역할을 발휘합니다. 
    예를 들어 정규식 "1^''나 "$1''에서의 ^, $는 그 역할을 하지 못하고, 
    단순히 일반 문자로 해석됩니다. 만약 실제로 문장의 첫 부분에 오는 ^이나, 
    문장의 마지막에 오는 $를 원한다면 이들 문자 앞에 \를 붙이면 됩니다. 


        표1: Regular Expression Anchor Character Examples  



        패턴        Matches
        -----------------------------------------------
        ^A           문장의 처음에 나오는 'A'
        A$            문장의 마지막에 나오는 'A'
        A^           아무곳에나 올수 있는 'A^'
        $A            아무곳에나 올수 있는 '$A'
        ^\^       문장의 처음에 나오는 '^'
        ^^           '^\^'과 동일
        \$$         문장의 마지막에 나오는 '$'


    이 문자들은 단지 정규식이 아닌 비슷한 의미로도 많이 쓰입니다. 
    예를 들어 vi의 명령 모드에서 `$'는 문장의 끝으로 커서를 이동하는 데에 쓰이며, 
    `^'는 문장의 처음으로 이동시키는 데에 쓰입니다. 


    또한 C shell에서 `!^'는 바로 전 줄의 첫번째 인자를 지정하는데에 쓰이고, 
    `!$'는 마지막 인자를 지정하는데에 쓰입니다. 

    다른 프로그램에서도 비슷한 명령들을 볼 수 있습니다. 
    ed와 sed에서 `$'는 파일의 마지막 줄을 의미하며, 
    `cat -v -e' 명령은 각 줄의 끝을 `$'로 나타내게 해 줍니다. 



4. Matching a Character with a Character Set 



    가장 간단한 문자 집합은 한 문자로 나타내는 것입니다. 
    예를 들어 정규식 `the'는 `t', `h', `e'의 세 문자로 이루어진 것이며, 문자열 `the'에만 match됩니다. 
    그러나 이 정규식은 `the' 뿐만 아니라 `other'에도 match될 수 있습니다. 
    이를 방지하려면 정규식의 앞에 (또는 뒷 부분, 또는 앞뒤 모두에) 공백을 주어 
    ` the'로 쓰면 `other'와 같은 단어에 match되는 것을 막을 수 있습니다. 



    앞에서 배운 anchor와 조합하면 여러가지로 응용할 수 있습니다. 
    예를 들어 자신에게 온 편지 중 보낸이의 목록을 알고 싶다면 다음과 같이 할 수 있습니다. 
    e-mail 형식상 보낸이는 ``From: xxx''의 형태로 기록됩니다. 
    따라서 정규식 `From'을 grep 명령에 쓰면 보낸이의 목록을 뽑을 수 있습니다. 
    하지만 단어 ``From''은 매우 빈번하게 쓰이는 것이라 필요없는 줄까지 출력할 경우가 예상됩니다. 
    이 때, 앞에서 배운 anchor인 `^'를 써서 다음과 같이 하면 - 100% 보장할 순 없지만 - 보낸이의 목록만을 얻을 수 있습니다: 


    $ grep '^From: ' /usr/spool/mail/$USER



    앞으로 설명할 몇몇 문자들은 정규식에서 특별한 뜻을 가집니다. 
    이러한 문자들을 글자 그대로의 의미로 쓰고 싶다면 앞에다 `\'를 붙이면 됩니다. 



5. Match any Character with `.' (Dot) 



    Dot (.) 문자는 정규식에서 한 글자에 해당합니다. 글자의 종류는 상관없습니다. 
    따라서 정규식 `...'은 세 글자로 구성된 단어에 해당합니다. 
    또한 한 글자로만 된 줄은 `^.$'로 나타낼 수 있습니다. 



6. Specifying a Range of Characters with [...] 



    특정 범위에 해당하는 글자를 나타내고 싶다면 [] 사이에 넣으면 됩니다. 
    예를 들어 `A', `B', `C' 세 글자 중 한 글자에 해당하는 정규식은 `[ABC]'입니다. 
    또한 한 숫자로만 이루어진 줄은 `^[0123456789]'로 쓸 수 있습니다. 
    Hyphen (`-') 문자를 써서 범위로 지정할 수 있습니다. 


    예를 들어 위에서 한 숫자만으로 이루어진 줄은 간단히 `^[0-9]'로 나타낼 수 있습니다. 
    알파벳, 숫자, 밑줄 문자 중 한 글자에 해당하는 정규식은 `[A-Za-z0-9_]입니다. 

    좀 더 복잡한 예를 들어 보면: 



    줄의 첫 문자가 `T'이고, 
    다음으로 소문자 한 글자가 나오고, 
    다음으로 알파벳 소문자 모음(vowel)이 나오고, 
    세 글자로 이루어진 (네 번째 문자가 `') 
    정규식은 `^T[a-z][aeiou] '입니다. 



7. Exceptions in a Character Set 



    []을 쓰면 주어진 범위에 해당하는 문자를 찾을 수 있습니다. 
    반대로 `^'을 함께 쓰면 주어진 범위에 해당하지 않은 문자를 찾습니다. 
    예를 들어 `[^aeiou]는 소문자 모음이 아닌 문자에 해당하는 정규식입니다. 
    이 때 `^' 문자는 반드시 `[' 다음에 와야 합니다. 


    다른 anchor들과 마찬가지로 제 자리에 오지 않은 문자들은 특별한 뜻을 가지지 않습니다. 
    예를 들어 `[' 문자 바로 뒤에 나오는 `]' 문자나 `[' 뒤에 바로 나오는 `-'은 일반 문자로 취급됩니다. 
    표2를 참고하기 바랍니다. 


        표 2: Regular Expression Character Set Examples 

        Regular Expression      Matches
        ------------------------------------------------------
        [0-9]                            숫자중에 한 글자
        [^0-9]                          숫자가 아닌 한 글자
        [-0-9]                           숫자나 '-' 한글자
        [^-0-9]                        숫자와 '-'가 아닌 한글자



8. Repeating Characteer Sets with * 



    정규식의 마지막 부분인 `modifier'는 바로 앞의 패턴의 반복 횟수를 지정합니다. 
    `*' 문자는 바로 앞 패턴이 0번 이상 나온다는 것을 의미합니다. 
    따라서 `0*'는 문자 `0'이 0개 이상 나올 수 있다는 것을 의미합니다. 
    따라서 간단한 10진 수치는 `[0-9]*'으로 표현할 수 있을 것입니다. 
    조심할 것은 1개 이상이 아닌 0개 이상이라는 것입니다. 


    예를 들어 문장의 첫 부분에서 `#'로 시작하는 단어를 찾기 위해 `^#*'를 쓴다면 
    `#'로 시작하는 줄은 당연히 포함되고, - 0번 반복일 경우 - `#'로 시작하지 않는 줄로 포함됩니다. 
    따라서 앞에서 다룬 10진 수치의 경우 좀 더 정확한 표현은 `[0-9][0-9]*'이 됩니다. 


9. Matching a Specific Number of Sets with \{ and \}



    `*'만으로는 최대 횟수를 지정할 수 없습니다. 
    몇몇 프로그램들에선 다음과 같은 횟수를 지정하는 정규식을 쓸 수 있습니다. 
    이는 두 개의 쌍으로 이루어진 특수 표현을 사용합니다: `\{'와 `\}'. 

    예를 들어 소문자 4 개에서 8개로 이루어진 문자열은 [a-z]\{4,8\}에 해당합니다. 
    횟수를 지정할 때 쓰이는 수치는 0에서 255 사이의 수치면 됩니다. 


    만약 두 번째 수치가 생략되면 *와 비슷하게 상위 경계에 적용받지 않습니다. 
    따라서 특수 문자 *는 \{0,\}와 같은 뜻입니다 .와 마찬가지로 이는 앞 패턴의 횟수를 지정하기 위해 쓰입니다. 
    따라서 이 표현이 문장의 처음에 나온다면 modifier의 기능을 잃고 일반 글자로 쓰이게 됩니다. 



        표 3: Regular Expression Pattern Repetition Examples 

        Regular Expression      Matches
        ------------------------------------------------------
        *                                  *로 시작되는 줄
        ^A*                              아무줄이나 해당
        ^AA*                           하나 이상의 A로 시작되는 줄
        ^AA*B                         하나 이상의 A로 시작되고 B로 끝나는 줄
        ^A\{4,8\}B              4~8개의 A자가 오고 B로 끝나는 줄


10. Matching words with \< with \>



    단어를 찾는 것은 때때로 복잡한 일이 될 수 있습니다. 
    예를 들어 `the'를 찾기 위해 the를 쓰더라도 `other'에 매치되는 경우가 있습니다. 
    이를 방지하기 위해 앞뒤에 공백을 넣는다 하더라도 `the'라는 단어가 줄의 맨 앞 부분이나
    뒷부분에 있다면 이 방법으로는 찾을 수 없습니다. 


    ed, ex, vi와 같은 프로그램은 이런 경우 단어(word) 단위로 검색할 수 있게 \<와 \>를 지원합니다. 
    즉 정규식 \<the\>는 `the'에는 매치되지만 `other'에는 매치되지 않습니다. 



11. Remembering Patterns with \(, \), and \1



    반복되는 단어를 찾을 때, 쓸 수 있는 유융한 기능입니다. 
    예를 들어 같은 글자가 반복되는, 두 글자로 이루어진 패턴을 찾을 때, [a-z][a-z]는 거의 쓸모가 없습니다. 
    \(와 \)는 이 사이의 패턴을 기억해 줍니다. 실제 이 패턴은 \1로 쓸 수 있습니다. 
    예를 들어 같은 글자가 반복되는, 두 글자로 이루어진 패턴은 \([a-z]\)\1로 쓸 수 있습니다.


    한 정규식에 여러 쌍의 \(와 \)가 있다면 \1, \2, \3등으로 쓸 수 있습니다. 최대 9까지 기억할 수 있습니다. 
    `Palindrome'이라는 것이 있습니다. 간단히 말해 앞으로 쓰나 뒤로 쓰나 같은 단어를 말합니다. 
    예를 들면 `radar'가 있습니다. 5글자로 된 palindrome을 찾으려면 정규식 \([a-z]\)\([a-z]\)[a-z]\2\1을 씁니다. 

    이는 특히 sed를 써서 문자열을 치환할 때에도 유융하게 쓰입니다. 


12. Potential Problem 



    확장 정규식을 다루기 전에 먼저 알고 넘어갈 것이 있습니다. 
    \<, \> 문자는 vi에서 처음 사용된 것입니다. 따라서 다른 프로그램에서는 지원하지 않을 수도 있습니다. 
    또한 \{, \}도 새로 등장한 것입니다. 오래된 프로그램에서는 지원하지 않을 가능성이 높습니다. 
    초보자가 흥미를 잃는 가장 큰 이유는 바로 이런 것 때문입니다. 


    즉 정규식은 그 종류가 다양하고 또, 100% 지원하는 프로그램이 드물기 때문입니다. 
    그러나 최근에 만들어진 대부분의 프로그램들은 대부분의 정규식을 지원하기 때문에 
    사용자의 시스템이 특별히 오래된 것이 아니면 무난하게 쓸 수 있을 것입니다. 
    또 하나의 문제는 조금 골치가 아픈 것입니다. 



    예를 들어 A.*B는 `AAB'에도 해당하지만 `AAAABBBBABCCCCBBBAAAB'에도 해당합니다. 
    얼핏 보면 문제가 없을 것 같지만 심각합니다. 예를 들어 위의 긴 문자열은 자체가 A.*B에 매치될 수도 있지만 
    작게 쪼개면 `AAAAB'도 정규식에 해당하고 `AB'도 해당하고, 마지막 `AAAB'도 해당하는 등, 여러 가지 경우가 나옵니다. 
    grep과 같은 프로그램은 단순히 주어진 정규식에 해당하는 줄을 출력해 주는 역할을 하므로 별 문제가 되지 않지만 
    sed와 같은 프로그램을 써서 정규식에 해당하는 표현을 다른 것으로 바꾼다고 할 때 문제가 발생합니다. 
    따라서 정규식을 써서 무언가를 바꾸거나 제거할 때에는 주의해야 합니다. 
    참고로 이런 경우에 정규식은 항상 가장 긴 문자열에 매치되려고 합니다. 


13. Regular Expression Examples 



    이 장에서는 정규식을 써서 만든 간단한 예제를 모았습니다. 



    미국 주(State) 표시: (NM) 
    [A-Z][A-Z]

    미국 주, 시(city) 표시 (Portland, OR) 
    ^.*, [A-Z][A-Z]

    미국식 날짜 표시 (JAN 05, 1993) (January 5, 1993) 
    [A-Z][A-Za-z]\{2,8\} [0-9]\{1,2\}, [0-9]\{4\}

    미국 주민번호 (123-45-6789) 
    [0-9]\{3\}-[0-9]\{2\}-[0-9]\{4\}

    전화번호 (547-5800) 
    [0-9]\{3\}-[0-9]\{4\}

    달러 ($1) ($ 1000000.00) 
    \$ *[0-9]+(\.[0-9][0-9])?

    HTML 태그 (<H2>) (<UL COMPACT>) 
    <[^>]*>

    빈 줄 
    ^$

    줄 전체 
    ^.*$

    하나 이상의 공백 
      *
----------------------------------------------

솔직히 어디서 퍼왔는지 출처를 알수 없네요..

작성해주신분께 감사드리며...
[출처 : http://www.coolsms.co.kr/?document_srl=62073]


이번에는 파이썬에서 PHP UTF-8 한글 자르기와 같은 내용으로 다뤄보겠습니다.


PHP와 마찬가지로 완성형 한글에서 한글 2바이트, 영어 1바이트 기준으로 잘라줍니다.


- UTF-8 한글 자르기

#-*- encoding: utf-8 -*-

import re


def strcut_utf8(str, destlen, checkmb=True, tail=""):

        """

         UTF-8 Format

          0xxxxxxx = ASCII, 110xxxxx 10xxxxxx or 1110xxxx 10xxxxxx 10xxxxxx

          라틴 문자, 그리스 문자, 키릴 문자, 콥트 문자, 아르메니아 문자, 히브리 문자, 아랍 문자 는 2바이트

          BMP(Basic Mulitilingual Plane) 안에 들어 있는 것은 3바이트(한글, 일본어 포함)

        """

        slen = len(str)

        tlen = len(tail)


        if slen <= destlen:

                return str


        pattern = "[\xE0-\xFF][\x80-\xFF][\x80-\xFF]"

        count=0

        text = []

        for match in re.finditer(pattern, str):

                if len(checkmb == True and match.group(0)) > 1:

                        count = count + 2

                else:

                        count = count + 1

                if (count + tlen) > destlen:

                        return "".join(text) + tail

                text.append(match.group(0))


        return "".join(text)
 


다음과 같이 5바이트를 잘라야하는데 완성형 한글 기준으로 봤을 때 5바이트 시작은 한글 '다'의 앞쪽 코드이기 때문에 한글이 깨어지지 않도록 4바이트까지만 잘라서 "가나" 문자열을 리턴합니다.


    print strcut_utf8("가나다라마바사아자차카타파하", 5, True, "")

    가나


아래와 같이 strlen 함수도 가능합니다.


- 완성형 한글 기준 크기 알아내기

#-*- encoding: utf-8 -*-

import re


def strlen_utf8(str):

        """

         UTF-8 Format

          0xxxxxxx = ASCII, 110xxxxx 10xxxxxx or 1110xxxx 10xxxxxx 10xxxxxx

          라틴 문자, 그리스 문자, 키릴 문자, 콥트 문자, 아르메니아 문자, 히브리 문자, 아랍 문자 는 2바이트

          BMP(Basic Mulitilingual Plane) 안에 들어 있는 것은 3바이트(한글, 일본어 포함)

        """

        pattern = "[\xE0-\xFF][\x80-\xFF][\x80-\xFF]"

        count=0

        for match in re.finditer(pattern, str):

                count = count + 1

        return count


[출처 : http://divestudy.tistory.com/8]


사실 한글 인코딩에는 관심이 없었다. 그냥 대충 처리해도 잘 보고 잘 쓸수 있기때문에??

이번에 초성검색에 대한 문제를 해결하는데 문제가 생겼다.
한글이 어떻게 저장 되있냐에 따라 초성 검색 방식이 달라지기 때문이다.
어줍잖은 지식으로 조합형으로 되있겠지라고 했지만 이게 왠걸?!
조합형으로 저장을 안하네 ㅎㄷㄷ 시스템마다 다름 윈도우는 기본적으로 euc-kr(완성형)
어쨌든 우분투에서 만들어야 하니 우분투 인코딩셋에대해서 알아본 결과
UTF-8 이란것을 알수 있었다 (locale 명령어로 알수 있음)
UTF-8 이라.. 어서 많이 들어 본 단어 인데;; 브라우져에서도 보고 파일 전송때도 보고..
알고 보니 UNICODE를 표현하는 방법 중에 하나라고 한다.(UTF-8 뿐만아니라 -16, -32 등도 있음)
어쨌든!! 이런건 인터넷에 널려 있으니 참고 하면 되고 변환 방법을 알아보자!!

유니코드는 전세계 모든언어를 표기하기위해 만들어졌지만 한글만 변환하므로 이에 관련된것만 보겠다.
"가"는 UNICODE로 AC 00 (16 진수 표기 , UAC00 라고도 표기한다 앞의 U는 유니코드를 나타낼때) 이고
U-00000800 - U-0000FFFF 범위에 들어가므로 비트 마스크(?)는 1110xxxx 10xxxxxx 10xxxxxx 이다.

즉, UTF-8로 표기시 1110xxxx 10xxxxxx 10xxxxxx 형태가 되며 x는 AC00를 순서대로 넣어주면 된다.
AC00 => 1010 1100 0000 0000 이며 차례 대로 넣어주면

11101010 10110000 10000000 로 변환된다. 이것을 16진수로 바꿔 주면 EA B0 80 이 된다.

다음으로 알아볼것은 UNICODE를 초성, 중성, 종성으로 분리하는 방법이다.

"갈"을 분리 해보자! "갈"은 유니코드로 UAC08이다.

1) 분리할 문자를 AC00으로 뺀다 ( 0xAC08 - 0xAC00 = 0x8)
2) 1의 결과를 21로 나누고 28로 나눈 몫은 초성이다. (8/21/28 = 0)
3) 1의 결과를 21*28로 나눈 나머지와 28로 나눈 몫은 중성이다 ( (8 % (21*28)) / 28 = 0)
4) 1의 결과를 28로 나눈 나머지는 종성이다 ( 8 % 28  = 8 )

초성은  0  중성은  0  종성은 8을 테이블에서 찾으면 된다.

초성 테이블

10  11  12  13  14  15  16  17  18 
 ㄱ  ㄲ   ㄴ  ㄷ  ㄸ  ㄹ  ㅁ  ㅂ  ㅃ  ㅅ  ㅆ  ㅇ  ㅈ   ㅉ   ㅊ   ㅋ   ㅌ   ㅍ   ㅎ 

중성 테이블
 0  1  2  3  4  5  6  7  8 10  11  12  13  14  15  16  17  18 
 ㅏ  ㅐ  ㅑ  ㅒ  ㅓ  ㅔ  ㅕ  ㅖ  ㅗ  ㅠ  ㅘ ㅛ   ㅙ  ㅚ  ㅜ  ㅝ  ㅞ  ㅟ  ㅡ
 19 20 
 ㅢ  ㅣ  

종성 테이블
 0  1  2  3  4  5  6  7  8 10  11  12  13  14   15  16  17  18
   ㄱ  ㄴ  ㄵ  ㄶ  ㄷ   ㄹ   ㄺ   ㄻ   ㄼ  ㄽ  ㄾ  ㄿ  ㅀ   ㅁ  ㅂ  ㅄ 
19  20  21  22  23  24  25  26  27
ㅅ  ㅆ  ㅇ   ㅈ  ㅊ  ㅋ   ㅌ  ㅍ  ㅎ 


"ㄱ" + "ㅏ" + "ㄹ" 인걸 알수 있다11 이젠 초성 검색 ㄱㄱ씽!!!

+ Recent posts