-
- 1. 문자열 잘라내기
-
-
- 1.1. EUC-KR 위키의 경우
-
- 1.2. encoding에 따라서 다르게 처리하기
-
- 1.3. Perl의 유니코드 처리를 이용
-
- 1.4. 의견
-
1. 문자열 잘라내기
어떤 문자열을, 자기가 원하는 만큼의 길이만큼 앞부분을 잘라내는 법
1.1. EUC-KR 위키의 경우
원하는 바이트만큼 잘라내고, 만일 제일 끝 바이트가 한글(2바이트)의 첫바이트일 경우, 그 바이트를 마저 잘라낸다. ext1 버전에서 사용된 방법
$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 = (
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/(?:(.*)(\/))?(.+)/);
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;
}
if ($HttpCharset =~ /euc-kr/i) {
my ($first, $tail) = ($page =~ /([a-zA-Z0-9]|[\x80-\xff][\x80-\xff])(.*)/);
return $mainpage . &GetEditLink($id,$slash.$first) . $tail;
}
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);
return $mainpage . &GetEditLink($id,$slash.$first) . $last;
}
위에 사용된 split_string 함수는 Perl/문자열나누기에 적어 두었음
위키위키분류