首页 | 注册 | 登录 | 归档 | 搜索 | 标签 | 在线工具

sablog的学习报告.

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

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

                        
$text    =    mb_substr($text,    0,    $limit,    'UTF-8');

                        return    array(
$text,    $more);

            }    elseif    (
function_exists('iconv_substr'))    {

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

                        
$text    =    iconv_substr($text,    0,    $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===1    ){            
                  
                              
      $cstr=substr($str,0,$limit+1).'(1)';
                  
                  
      //如果非汉字类为偶数,长度不变            
                  
      }else    {
                  
                              
      $cstr=substr($str,0,$limit).'(0)';
                              
                  }
                  
      }

Tags: php, 学习, sablog

Address: http://www.amxku.net/archives/750/

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

相关文章

网友评论

http://blog.csdn.net/heiyeshuwu/archive/2006/11/20/1396961.aspx
Post by amxku on 2006-11-20, 13:11 Quote #1

发表评论

评论内容: