[첫화면으로]UTF-8이전작업/문자열잘라내기

마지막으로 [b]

1. 문자열 잘라내기
1.1. EUC-KR 위키의 경우
1.2. encoding에 따라서 다르게 처리하기
1.3. Perl의 유니코드 처리를 이용
1.4. 의견

1. 문자열 잘라내기

어떤 문자열을, 자기가 원하는 만큼의 길이만큼 앞부분을 잘라내는 법

1.1. EUC-KR 위키의 경우

원하는 바이트만큼 잘라내고, 만일 제일 끝 바이트가 한글(2바이트)의 첫바이트일 경우, 그 바이트를 마저 잘라낸다. ext1 버전에서 사용된 방법
# 트랙백 내용을 처음 252바이트만큼 잘라내기
$excerpt = substr($excerpt, 0, 252);
$excerpt =~ s/(([\x80-\xff].)*)[\x80-\xff]?$/$1/;    # 마지막 바이트 처리

1.2. encoding에 따라서 다르게 처리하기

UTF-8이 되면 한 글자가 2바이트일 수도 있고 3바이트일 수도 있으므로 위의 방법으로는 제대로 잘리지 않는다.

존재하지 않는 페이지의 경우 페이지 이름의 "첫 글자"를 잘라내어서 거기에 링크를 걸어야 하는데, 별 수 없이 인코딩이 뭐냐에 따라서 다르게 처리했다. UTF-8의 경우는 첫 바이트를 보고, "그 바이트 뒤에 몇 개의 바이트가 더 와야 하나의 글자가 되는지"를 판단한 후, 해당 길이만큼 잘라내도록 하였었다.

아래 코드의 경우는 첫 한 글자만 뽑아내는 경우이고, 만일 여러 글자를 뽑아내기 위해서는 저 과정을 다시 뽑아내려는 갯수만큼 반복해야 했을 것이다. 더 이상 사용되지 않는 코드인데, 기록 보존 차원에서 여기 적어둠.

sub GetFirstCharLink {
# 첫 글자에 링크를 거는 함수
    my ($id, $name) = @_;
    my @trailingBytesForUTF8 = ( # ftp://ftp.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c 에서 옮겨왔음
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
    );

    my ($mainpage, $slash, $page) = ($name =~ m/(?:(.*)(\/))?(.+)/);

# utf-8
    if ($HttpCharset =~ /utf-8|utf8/i) {
        my $length = $trailingBytesForUTF8[ord(substr($page,0,1))] + 1;   # 첫 바이트를 보고 첫 글자의 길이를 계산
        my $first = substr($page,0,$length);                              # 이게 첫 글자
        my $tail = substr($page,$length);                                 # 이게 나머지 문자열
        return $mainpage . &GetEditLink($id,$slash.$first) . $tail;
    }

# euc-kr
    if ($HttpCharset =~ /euc-kr/i) {                                      # 이와 같이, 모든 인코딩에 대해 각각 처리해주어야 한다 -_-;
        my ($first, $tail) = ($page =~ /([a-zA-Z0-9]|[\x80-\xff][\x80-\xff])(.*)/);

        return $mainpage . &GetEditLink($id,$slash.$first) . $tail;
    }

# default
    return &GetEditLink($id, $name);
}

1.3. Perl의 유니코드 처리를 이용

"가나다"라는 문자열은, EUC-KR에서는 "%B0%A1%B3%AA%B4%D9" (6바이트), UTF-8에서는 "%EA%B0%80%EB%82%98%EB%8B%A4" (9바이트)로 표현된다.

그런데, Perl 코드에서 "\x{AC00}\x{B098}\x{B2E4}"와 같이, 유니코드 테이블에서의 가,나,다의 인덱스를 적어주어서 표현할 경우, 이것은 바이트와 무관하게 "3글자"로 표현된다. 따라서 정규표현식에서 "."이 1개의 글자를 의미하기 때문에, 영어든 한글이든 뭐든간에 "."으로 한글자를 정확히 뽑아낼 수 있다.

문제는 "EUC-KR 또는 UTF-8로 된 스트링을 어떻게 저 유니코드 표현으로 바꾸느냐"였는데... 보아하니 저 유니코드 표현이라는 것이 바로 "UNICODE"라는 이름의 인코딩인 것 같더라. 즉 EUC-KR 또는 UTF-8에서 UNICODE로 인코딩 컨버트를 하면 되는 것이었음. (사실 이건 순전히 막무가내 테스트 도중에 요행히 발견한 것이라... 정확한 건지 모르겠다. UNICODE 인코딩의 경우 시스템의 big/little endian 에 따라서 또 달라지는 것 같던데...)

따라서, 위키에서 사용되는 인코딩(HttpCharset)을 UNICODE로 변환하여 문자열 처리를 한 후, 다시 출력할 때는 HttpCharset으로 재변환해주면, EUC-KR위키와 UTF-8위키 두 곳에서 다 잘 되는 것으로 보인다.

첫 글자에 링크 걸기는 아래와 같이 간단히 바뀐다.
# 첫 글자에 링크를 거는 함수
sub GetFirstCharLink {
    my ($id, $name) = @_;

    my ($mainpage, $slash, $page) = ($name =~ m/(?:(.*)(\/))?(.+)/);
    my ($first, $last) = &split_string($page, 1);                    # $page의 첫 1글자는 $first에, 나머지 문자열은 $last에 들어감

    return $mainpage . &GetEditLink($id,$slash.$first) . $last;
}

위에 사용된 split_string 함수는 Perl/문자열나누기에 적어 두었음

1.4. 의견

이름:  
Homepage:
내용:
 

위키위키분류

마지막 편집일: 2007-2-22 1:29 am (변경사항 [d])
1021 hits | Permalink | 변경내역 보기 [h] | 페이지 소스 보기