utf-8 문자열 자르기.

cdpark의 이미지

utf-8 문자열 자르기 함수를 php 코드로 만들어봤습니다. 주어진 길이보다 짧게 재단하는 함수죠. (제 첫 php 코딩인 듯.)

function u8_strcut($str, $limit)
/* Note: */
/* $str must be a valid UTF-8 string */
/* it may return an empty string even if $limit > 0 */
{
   $len= strlen($str);

   if ($len<= $limit )
      return $str;

   $len= $limit;

   /* ASCII are encoded in the range 0x00 to 0x7F
    * The first byte of multibyte sequence is in the range 0xC0 to 0xFD.
    * All furthur bytes are in the range 0x80 to 0xBF.
    */

   while ($len > 0 && ($ch = ord($str[$len])) >= 128 && ($ch < 192))
        $len --;

   return substr($str, 0, $len);
}

mb_strcut() 함수를 쓸 수 없는 상황에서 UTF-8를 위해 쓰도록 만든 겁니다. (drupal 때문이라고는...)
php 전문가 분이 좀 더 성능이나 코딩 스타일 등을 손봐주세요.

순선 님의 해법은 어떤 것인가요?

Forums: 
lsj0713의 이미지

순선 님은 아니지만 답변을 달겠습니다 :-) 제가 쓰는 함수는 다음과 같습니다.

// function cut_string_utf8($str, $max_len, $suffix)
// 유니코드용 문자열 자르기 함수.
//
function cut_string_utf8($str, $max_len, $suffix)
{
	$n = 0;
	$noc = 0;
	$len = strlen($str);
	while ( $n < $len )
	{
		$t = ord($str[$n]);
		if ( $t == 9 || $t == 10 || (32 <= $t && $t <= 126) )
		{
			$tn = 1;
			$n++;
			$noc++;
		}
		else if ( 194 <= $t && $t <= 223 )
		{
			$tn = 2;
			$n += 2;
			$noc += 2;                     
		}
		else if ( 224 <= $t && $t < 239 )
		{
			$tn = 3;
			$n += 3;
			$noc += 2;
		}
		else if ( 240 <= $t && $t <= 247 )
		{
			$tn = 4;
			$n += 4;
			$noc += 2;
		}
		else if ( 248 <= $t && $t <= 251 )
		{
			$tn = 5;
			$n += 5;
			$noc += 2;
		}
		else if ( $t == 252 || $t == 253 )
		{
			$tn = 6;
			$n += 6;
			$noc += 2;
		}
		else { $n++; }
		if ( $noc >= $max_len ) { break; }
	}
	if ( $noc <= $max_len ) return $str;
	if ( $noc > $max_len ) { $n -= $tn; }
	return substr($str, 0, $n) . $suffix;
}

이 함수의 제한 사항은, 반드시 valid UTF-8 string 이어야 한다는 겁니다. ASCII code 0~127인 문자는 1글자로 치고 멀티바이트 문자는 2글자로 칩니다. 게시판의 제목 자를때 쓰는 함수라서... $suffix는 문자 길이가 $max_len 보다 길 경우에, 잘라내고 그 뒤에 붙일 문자열을 뜻합니다.

$str = cut_string_utf8("abcdefg", 4, "...");

라 하면 $str = "abcd..."; 가 되는 겁니다.

익명 사용자의 이미지

lsj0713 wrote:
순선 님은 아니지만 답변을 달겠습니다 :-) 제가 쓰는 함수는 다음과 같습니다.

// function cut_string_utf8($str, $max_len, $suffix)
// 유니코드용 문자열 자르기 함수.
//
function cut_string_utf8($str, $max_len, $suffix)
{
	$n = 0;
	$noc = 0;
	$len = strlen($str);
	while ( $n < $len )
	{
		$t = ord($str[$n]);
		if ( $t == 9 || $t == 10 || (32 <= $t && $t <= 126) )
		{
			$tn = 1;
			$n++;
			$noc++;
		}
		else if ( 194 <= $t && $t <= 223 )
		{
			$tn = 2;
			$n += 2;
			$noc += 2;                     
		}
		else if ( 224 <= $t && $t < 239 )
		{
			$tn = 3;
			$n += 3;
			$noc += 2;
		}
		else if ( 240 <= $t && $t <= 247 )
		{
			$tn = 4;
			$n += 4;
			$noc += 2;
		}
		else if ( 248 <= $t && $t <= 251 )
		{
			$tn = 5;
			$n += 5;
			$noc += 2;
		}
		else if ( $t == 252 || $t == 253 )
		{
			$tn = 6;
			$n += 6;
			$noc += 2;
		}
		else { $n++; }
		if ( $noc >= $max_len ) { break; }
	}
	if ( $noc <= $max_len ) return $str;
	if ( $noc > $max_len ) { $n -= $tn; }
	return substr($str, 0, $n) . $suffix;
}

이 함수의 제한 사항은, 반드시 valid UTF-8 string 이어야 한다는 겁니다. ASCII code 0~127인 문자는 1글자로 치고 멀티바이트 문자는 2글자로 칩니다. 게시판의 제목 자를때 쓰는 함수라서... $suffix는 문자 길이가 $max_len 보다 길 경우에, 잘라내고 그 뒤에 붙일 문자열을 뜻합니다.

$str = cut_string_utf8("abcdefg", 4, "...");

라 하면 $str = "abcd..."; 가 되는 겁니다.


문제는 한글이 유니코드 상황에서 3글자로 되어 있다는 것입니다.
정태영의 이미지

3바이트를 넘는 경우까지는 처리하지 않고 그냥 테스트 성으로 예전에 만들어 놓은 코드가 있어서 저도 흐흐흐

http://mytears.org/resources/mysrc/php/base64/test.php
http://mytears.org/resources/mysrc/php/unicode/utf8.php

http://b.mytears.org/2005/11/28/rfc2047-message-header-extensions-for-non-ascii-text/

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

익명 사용자의 이미지

Quote:
문제는 한글이 유니코드 상황에서 3글자로 되어 있다는 것입니다.
위의 코드 제대로 이해 못하셨군요. 다시 생각해 보십시오.
dharana의 이미지

lsj0713님의 코드에서
if ( $noc >= $max_len ) { break; }
부분을
if ( $noc > $max_len ) { break; }
로 바꿔줘야 ascii 도 제대로 자를 수 있습니다.

DarKMinD의 이미지

lsj0713 wrote:
순선 님은 아니지만 답변을 달겠습니다 :-) 제가 쓰는 함수는 다음과 같습니다.

// function cut_string_utf8($str, $max_len, $suffix)
// 유니코드용 문자열 자르기 함수.
//
function cut_string_utf8($str, $max_len, $suffix)
{
	$n = 0;
	$noc = 0;
	$len = strlen($str);
	while ( $n < $len )
	{
		$t = ord($str[$n]);
		if ( $t == 9 || $t == 10 || (32 <= $t && $t <= 126) )
		{
			$tn = 1;
			$n++;
			$noc++;
		}
		else if ( 194 <= $t && $t <= 223 )
		{
			$tn = 2;
			$n += 2;
			$noc += 2;                     
		}
		else if ( 224 <= $t && $t < 239 )
		{
			$tn = 3;
			$n += 3;
			$noc += 2;
		}
		else if ( 240 <= $t && $t <= 247 )
		{
			$tn = 4;
			$n += 4;
			$noc += 2;
		}
		else if ( 248 <= $t && $t <= 251 )
		{
			$tn = 5;
			$n += 5;
			$noc += 2;
		}
		else if ( $t == 252 || $t == 253 )
		{
			$tn = 6;
			$n += 6;
			$noc += 2;
		}
		else { $n++; }
		if ( $noc >= $max_len ) { break; }
	}
	if ( $noc <= $max_len ) return $str;
	if ( $noc > $max_len ) { $n -= $tn; }
	return substr($str, 0, $n) . $suffix;
}

이 함수의 제한 사항은, 반드시 valid UTF-8 string 이어야 한다는 겁니다. ASCII code 0~127인 문자는 1글자로 치고 멀티바이트 문자는 2글자로 칩니다. 게시판의 제목 자를때 쓰는 함수라서... $suffix는 문자 길이가 $max_len 보다 길 경우에, 잘라내고 그 뒤에 붙일 문자열을 뜻합니다.

$str = cut_string_utf8("abcdefg", 4, "...");

라 하면 $str = "abcd..."; 가 되는 겁니다.

제가 듣기론 저 위의 코드는 현제 UTF-8의 규격(?)에 맞지 않는다고 들었습니다.
(사실인지는 잘 모르지만요 ~_~)
지건 6바이트 까지 처리 해 주지만 현제까지는 6바이트 까지 언어가 정해져 있지 않다고 들었습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.