[Python] 결합 문자를 사용한 탁점이나 반탁점을 직전의 가명과 결합시키는 방법(우→브)

머리



사람명 검색을 실시할 수 있는 데이터베이스를 만들 때, 제공된 데이터에 이런 읽기 가명이 혼재하고 있었다.
  • 야마구치
  • 야마쿠 치

  • 야마구치와 검색해도 야맥゛치씨가 히트하지 않기 때문에, 「쿠゛」를 「그」에 가까이 하는 형태로 정규화하기로 했다.
    적당한 도서관이 보이지 않았기 때문에, 스스로 구현하기로 한 분투기.

    구현 방법


  • 문자열의 합성 문자를 기본 문자와 결합 문자로 분해
  • 1로 분해 된 문자열을 바이트 열로 변환
  • 2로 변환 된 바이트 열의 탁점, 반 탁점을 유니 코드 결합 문자의 탁점, 반 탁점으로 대체
  • 3으로 대체 된 바이트 열을 문자열 형식으로 되돌립니다.
  • (필요한 경우) 합성 문자로 변환

  • 유니코드 합성 및 결합 문자



    일본어의 「하」 「바」 「파」와 같이 부호의 유무·종류로 소리를 표현하는 문자에 대해, Unicode에서는 합성 문자와 결합 문자를 사용하는 2가지의 표현 방법이 있다.

    「바」의 예에서는 이하의 2종류가 있다.
  • U+3070
  • + 탁점 U+306F + U+3099
  • 는 합성 문자, 는 기본 문자, 탁점은 결합 문자입니다.

    탁점 또는 반탁점
    Wikipedia에는 ​​알기 쉬운 보기가 있기 때문에 인용한다.

    예 : â는 U + 00E2 (latin small letter a with circumflex) 또는 U + 0061 U + 0302 (latin small letter a + combining circumflex accent)로 나타낼 수 있습니다.
    결합 문자 - Wikipedia

    UTF-8의 합성 문자와 결합 문자



    Unicode상에서의 합성 문자와 결합 문자의 동작을 알았는데, Unicode에 대응한 문자 부호화 방식으로 제일 메이저일 UTF-8로 합성 문자와 결합 문자의 움직임을 본다.

    합성 문자


    import unicodedata
    
    print(unicodedata.normalize("NFC", "ヤ マ グ チ").encode())
    > b'\xe3\x83\xa4 \xe3\x83\x9e \xe3\x82\xb0 \xe3\x83\x81'
    

    "야마구치"의 구가, \xe3\x82\xb0 로 encode 되어 있다

    조인 문자


    import unicodedata
    
    print(unicodedata.normalize("NFD", "ヤ マ グ チ").encode())
    > b'\xe3\x83\xa4 \xe3\x83\x9e \xe3\x82\xaf\xe3\x82\x99 \xe3\x83\x81'
    

    "야마구치"의 구는 \xe3\x82\xaf\xe3\x82\x99의 조합으로 인코딩됩니다.

    탁점·반탁점의 문자 부호



    유니코드와 UTF-8에서 각각 대응하는 부호를 알 필요가 있지만, Wikipedia에 있었다.

    탁점 - Wikipedia
    반탁점 - Wikipedia


    기호
    유니코드
    UTF-8 부호
    비고



    U+309B
    \xe3\x82\x9b
    전각 탁점

    -
    U+3099
    \xe3\x82\x99
    탁점 (결합 문자)


    U+FF9E
    \xef\xbe\x9e
    반각 탁점


    U+309C
    \xe3\x82\x9c
    전각 반탁점

    -
    U+309A
    \xe3\x82\x9a
    반 탁점 (결합 문자)


    U+FF9F
    \xef\xbe\x9f
    반각 반탁점


    전각 탁점과 반각 탁점을 탁점 (결합 문자)으로 치환,
    전각 반탁점과 반각 반탁점을 반탁점 (결합 문자)으로 대체

    코드


    #!/usr/bin/env python3
    
    import re
    import unicodedata
    
    def join_diacritic(text, mode="NFC"):
        """
        基底文字と濁点・半濁点を結合
        """
        # str -> bytes
        bytes_text = text.encode()
    
        # 濁点Unicode結合文字置換
        bytes_text = re.sub(b"\xe3\x82\x9b", b'\xe3\x82\x99', bytes_text)
        bytes_text = re.sub(b"\xef\xbe\x9e", b'\xe3\x82\x99', bytes_text)
    
        # 半濁点Unicode結合文字置換
        bytes_text = re.sub(b"\xe3\x82\x9c", b'\xe3\x82\x9a', bytes_text)
        bytes_text = re.sub(b"\xef\xbe\x9f", b'\xe3\x82\x9a', bytes_text)
    
        # bytet -> str
        text = bytes_text.decode()
    
        # 正規化
        text = unicodedata.normalize(mode, text)
    
        return text
    
    

    실행
    join_diacritic("ルイズ・フランソワーズ・ル・ブラン・ド・ラ・ウ゛ァリエール")
    > ルイズフランソワーズブランヴァリエール
    

    응용



    바리에 짱을 우아리에 짱으로 하고 싶다.
        # 一度結合文字へ変換して
        text = unicodedata.normalize("NFD", text)
    
        # 結合文字を全角濁点・半濁点へ変換すればできる
        bytes_text = re.sub(b'\xe3\x82\x99', b"\xe3\x82\x9b", bytes_text)
        bytes_text = re.sub(b"\xe3\x82\x9a", b'\xe3\x82\x9c', bytes_text)
    

    UTF-8 이외의 문자 부호화 방식에 대응
        # 例えばこの様に実装にすれば、UTF-8以外にも対応できる
        bytes_text = re.sub("\u309B".encode(charset), "\u3099".encode(charset), bytes_text)
        bytes_text = re.sub("\uFF9E".encode(charset), "\u3099".encode(charset), bytes_text)
    

    결론



    유니 코드 결합 문자의 작동 방식을 사용하기 때문에 Shift_JIS 또는 친구는 유니 코드에 따라 문자 인코딩 방식으로 인코딩하여 사용할 수 있습니다 (아마도).

    좋은 웹페이지 즐겨찾기