首页 > PHP > strrev中文版反转字符串

strrev中文版反转字符串

PHP官方出品的strrev函数只支持英文字符反转,对于中文字符会出现乱码!只能通过编码识别后进行反转,好在以前研究过大量的字符串编码截取函数,所以给strrev适配一个中文版小菜一碟。代码如下:

//strrev中文版
function strrev_cn($str){
    $len = strlen($str);
    $r = array();
    $n = 0;
    $m = 0;
    for($i = 0; $i < $len; $i++)
    {
        $x = substr($str, $i, 1);
        $a  = base_convert(ord($x), 10, 2);
        $a = substr('00000000'.$a, -8);
        if (substr($a, 0, 1) == 0)
        {
            array_unshift($r, substr($str, $i, 1));
        }elseif (substr($a, 0, 3) == 110){
            array_unshift($r, substr($str, $i, 2));
            $i += 1;
        }elseif (substr($a, 0, 4) == 1110){
            array_unshift($r, substr($str, $i, 3));
            $i += 2;
        }else{
            array_unshift($r, '');
        }
        if (++$m >= $len)
        {
            break;
        }
    }
    return implode('', $r);
}

原理很简单,通过编码识别将每一个字符(如果是单个中文字也算一个字符,单个英文字也算一个字符)倒序放到一个数组中,然后连接输出即可,例如:

<?php
header('Content-type:text/html;charset=utf-8');

$str = '纠结伦';
//直接使用原生的strrev会给你一串乱码
//echo strrev($str);
//经过中文适配后的会返回"伦结纠"
echo strrev_cn($str);

这个中文版的strrev目前在网页采集中用处很大,例如上次讲的采集程序:

《读:我用爬虫一天时间“偷了”知乎一百万用户,只为证明PHP是世界上最好的语言》

那篇文章中使用的get_middle_reverse函数在逆向截取英文时能正常工作,一旦遇到中文字符全线崩溃。

这里提供了中文适配版(兼容英文版)

//反转截取
function get_middle_reverse($haystack, $left = '', $right = '')
{
    $revhtml = strrev_cn($haystack);
    $revsuffix = strrev_cn($right);
    $revpreffix = strrev_cn($left);
    $middle = subByString($revhtml, $revsuffix, $revpreffix);
    $result = strrev_cn($middle);
    return $result;
}

完整的例子如下:

<?php
header('Content-type:text/html;charset=utf-8');

//最后一页的超链接,如何才能获取30这个数字
$str = '<a href="?page=30">尾页</a>';

//使用逆向截取,将标识字符串功能转移到第三个参数
print_r('<pre>');
//">lastPage</a>是仅有一次的标识字符串,而page=却多次出现
//打印出30
print_r(get_middle_reverse($str, 'page=', '">尾页</a>'));
print_r('</pre>');

/**
 * 用于字符串截取,用于截取2个字符串之间的内容,不含边界
 * @param string $haystack
 * @param string $left
 * @param string $right
 * @return string
 */
function subByString($haystack, $left = '', $right = '')
{
    $left_pos = false;
    $right_pos = false;
    if($left == '' || ($left_pos = strpos($haystack, $left)) === false)
    {
        $start_pos = 0;
    }else{
        $start_pos = $left_pos;
    }
    $right_data = substr($haystack, $start_pos + ($left_pos === false ? 0 : strlen($left)));
    if($right == '' || ($right_pos = strpos($right_data, $right)) === false)
    {
        return substr($haystack, $left_pos === false ? 0 : $left_pos+strlen($left));
    }else{
        $end_pos = $start_pos + $right_pos;
        return substr($haystack, $left_pos === false ? 0 : $left_pos+strlen($left), $end_pos-$start_pos);
    }
}

//反转截取
function get_middle_reverse($haystack, $left = '', $right = '')
{
    $revhtml = strrev_cn($haystack);
    $revsuffix = strrev_cn($right);
    $revpreffix = strrev_cn($left);
    $middle = subByString($revhtml, $revsuffix, $revpreffix);
    $result = strrev_cn($middle);
    return $result;
}


//strrev中文版
function strrev_cn($str){
    $len = strlen($str);
    $r = array();
    $n = 0;
    $m = 0;
    for($i = 0; $i < $len; $i++)
    {
        $x = substr($str, $i, 1);
        $a  = base_convert(ord($x), 10, 2);
        $a = substr('00000000'.$a, -8);
        if (substr($a, 0, 1) == 0)
        {
            array_unshift($r, substr($str, $i, 1));
        }elseif (substr($a, 0, 3) == 110){
            array_unshift($r, substr($str, $i, 2));
            $i += 1;
        }elseif (substr($a, 0, 4) == 1110){
            array_unshift($r, substr($str, $i, 3));
            $i += 2;
        }else{
            array_unshift($r, '');
        }
        if (++$m >= $len)
        {
            break;
        }
    }
    return implode('', $r);
}

注意:使用strrev_cn反转某些字符可能会导致内存泄露,具体原因暂不明确,慎用!

文章地址:http://blog.zhengshuiguang.com/php/strrev-cn.html

转载随意^^请带上本文地址!

标签:strrev中文版 反转字符串 逆向截取

评论已关闭