sablog的学习报告.

function csubstr($text$start=0$limit=12) {    
         if (
function_exists('mb_substr'
)) {

                  
$more = (mb_strlen($text) > $limit) ? TRUE FALSE
;

                  
$text mb_substr($text0$limit'UTF-8'
);

                  return array(
$text$more
);

         } elseif (
function_exists('iconv_substr'
)) {

                  
$more = (iconv_strlen($text) > $limit) ? TRUE FALSE
;

                  
$text iconv_substr($text0$limit'UTF-8'
);

                  return array(
$text$more
);

         } else {

                  
preg_match_all("/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/"$text$ar
);         

                  if(
func_num_args() >= 3
) {         

                           if (
count($ar[0])>$limit
) {

                                    
$more TRUE
;

                                    
$text join("",array_slice($ar[0],0,$limit))."..."


                           } else {

                                    
$more FALSE
;

                                    
$text join("",array_slice($ar[0],0,$limit
)); 

                           }

                  } else {

                           
$more FALSE
;

                           
$text =         join("",array_slice($ar[0],0
)); 

                  }

                  return array(
$text$more
);

         } 

}
csubstr()的功能就是截节生成缩略文本字串的功能。单纯的我,以很久以前,一直以为不需要csubstr()直接用php自带的substr()就行了。可以,真的可以,只不过十分不好看。因为在中英混排时,奇数英文个数的单词或者其它半角等特殊情况会使中文单字被截断,这样就会出现一个滑稽的"?"号.这是一个无法正常显示的ascII码。经常也会出现点小问题。那就郁闷了..

似乎很早以前,有位达人,给了我一个简单的csubstr()例子,是通过逐字进行遍例,统计字串中半角、英文、其它可能出现的单字节的字符个数奇偶情况来作最后缩略文的limit值。这个方法,我现在想起来还心寒。。要是缩略文不用于标题,而是用于半文缩略,那是多大的工程啊!?

看到sablog的csubstr()后,似乎好像是用正则进行替换的。这种方法直接对limit最后一个字符进行处理。效率,想想都知道。没得说了,最优啦。所以开始对正则进行了研究。。
当正则学习到一定程度后。我开始回头看sablog的csubstr函数.顺路作了一下小研究(关于编码)。

代码如下:

<?php
         $str
='我'
;
         
         echo 
'$str:'.$str.'<br />'
;
         echo 
'String length: '.strlen($str).'<br />'
;
         echo 
'ord($str):'.ord($str).'<br />'
;
         
$sstr[1]=substr($str,0,1
);
         
$ostr[1]=ord($sstr[1
]);
         echo 
'echo $str(0,1):'.$sstr[1].' Ord:'.$ostr[1].' DecHex:'.dechex($ostr[1]).'<br />'
;
         
         
$sstr[2]=substr($str,1,1
);
         
$ostr[2]=ord($sstr[2
]);
         echo 
'echo $str(1,1):'.$sstr[2].' Ord:'.$ostr[2].'<br />'
;
         
         
$sstr[3]=substr($str,2,1
);
         
$ostr[3]=ord($sstr[3
]);
         echo 
'echo $str(0,1):'.$sstr[3].' Ord:'.$ostr[3].'<br />'
;
         
         
$sstr[0]=chr($ostr[1]).chr($ostr[2]).chr($ostr[3
]);
         echo 
'Join Ord(1-3):'.$sstr[0].'<br />'
;
?>
这段代码在UTF8与GB2312下有两种结果。
在UTF8下php脚本的结果如下:
$str:
String length
3
ord
($str):230
echo $str(0,1):� Ord:230 DecHex:e6
echo $str(1,1):� Ord:136
echo $str(0,1):� Ord:145
Join Ord
(1-3):
在GB2312下php脚本的结果如下:
$str:
String length
2
ord
($str):206
echo $str(0,1):� Ord:206 DecHex:ce
echo $str(1,1):� Ord:210
echo $str(0,1): Ord:0
Join Ord
(1-3):
关于正则部份的分析总结:

\xhh 在php manual里的说明:
在“\x”之后最多再读取两个十六进制数字(其中的字母可以是大写或小写)。在 UTF-8 模式下,允许用“\x{...}”,花括号中的内容是表示十六进制数字的字符串。原来的十六进制转义序列 \xhh 如果其值大于 127 的话则匹配了一个双字节 UTF-8 字符。



解读:
\x01-\x7f 这是一个十六进制的字符类,换算为十进制的数值解读:

  1. (\x01-\x7f) = (1-127) *GB2312的非汉字ASCII码
  2. (\xc2-\xdf) = (194-223) *未知
  3. (\x80-\xbf) = (128-191) *未知
  4. (\xe0)=(224) *未知
  5. (\xa0-\xbf) = (160-191) *未知
  6. (\xe1-\xef) = (225-239) *未知
  7. (\xf0) = (240) *未知
  8. (\x90) = (144) *未知
  9. (\xf1-\xf7) = (241-247) *未知


我知道未知部份有一部份是ascii码,但不知道为什么要分这么细。。
下面这部分是我的个人推理。。未证实的:


  1. [\x01-\x7f],匹配英文大小写与一些符号.
  2. [\xc2-\xdf][\x80-\xbf],匹配GB2312的ASCII编码,length=2
  3. \xe0[\xa0-\xbf][\x80-\xbf]~[\xe1-\xef][\x80-\xbf][\x80-\xbf],匹配UTF8的ASCII编码范围,length=3
  4. \xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf],没见过四连的ASCII编码值。。不知道这个是什么。不过估计是汉字中文.难道是UTF-16?


终于我自已写了一个小小的中文(汉字)截取函数的方法:

    • 只争对GB2312编码。
    • 只争对短标题控制。
      $str='中华a人民a共和国';

      $cstr=substr($str,0,10);

      preg_match_all("/[^\x7e-\xFF]/",$cstr,$preg);

      $azt=count($preg[0]); //非汉字ascII码个数统计

      $slen=strlen($cstr); //截取的标题长度

      $lstr=ord($cstr{$slen-1}); //最后一个字符的ASCII码的ORD值

      $limit=10//节取长度

      //最后的字符大于127则..
      if( $lstr chr(127)) {
               
               
      //如果非汉字类为奇数,长度+1
               
      if( $azt%2===){         
               
                        
      $cstr=substr($str,0,$limit+1).'(1)';
               
               
      //如果非汉字类为偶数,长度不变         
               
      }else {
               
                        
      $cstr=substr($str,0,$limit).'(0)';
                        
               }
               
      }

关键词: 学习 , sablog , php

上一篇: Sebug.net正式版 上线
下一篇: 最伟大的IT人物10强

相关文章
访客评论
#1
回复 amxku 2006-11-20, 13:11:33
http://blog.csdn.net/heiyeshuwu/archive/2006/11/20/1396961.aspx
发表评论

评论内容 (必填):