Comment inverser une chaîne Unicode

il a été suggéré dans un commentaire à une réponse à cette question que PHP ne peut pas inverser les chaînes Unicode.

quant à Unicode, il fonctionne en PHP parce que la plupart des applications le traitent comme binaire. Oui, PHP est 8-bit clean. Essayer l'équivalent de ce en PHP: perl -Mutf8 -e 'print scalaire inverse("ほげほげ")", Vous obtiendrez des ordures, pas "げほげほ". - jrockway!--4-->

et malheureusement il est correct que le support ATM de PHPs unicode est au mieux "absent". Ce sera espérons changer radicalement avec PHP6.

PHPs multi-octets fonctions fournit la fonctionnalité de base dont vous avez besoin pour traiter unicode, mais elle est incohérente et manque de beaucoup de fonctions. L'une d'elles est une fonction pour inverser une chaîne de caractères.

j'ai bien sûr voulu inverser ce texte pour aucune autre raison, alors, de savoir si c'était possible. Et j'ai fait une fonction pour accomplir cette tâche énorme et complexe d'inverser cette Texte Unicode, de sorte que vous pouvez vous détendre un peu plus longtemps jusqu'à PHP6.

Code de Test:

$enc = 'UTF-8';
$text = "ほげほげ";
$defaultEnc = mb_internal_encoding();

echo "Showing results with encoding $defaultEnc.nn";

$revNormal = strrev($text);
$revInt = mb_strrev($text);
$revEnc = mb_strrev($text, $enc);

echo "Original text is: $text .n";
echo "Normal strrev output: " . $revNormal . ".n";
echo "mb_strrev without encoding output: $revInt.n";
echo "mb_strrev with encoding $enc output: $revEnc.n";

if (mb_internal_encoding($enc)) {
    echo "nSetting internal encoding to $enc from $defaultEnc.nn";

    $revNormal = strrev($text);
    $revInt = mb_strrev($text);
    $revEnc = mb_strrev($text, $enc);

    echo "Original text is: $text .n";
    echo "Normal strrev output: " . $revNormal . ".n";
    echo "mb_strrev without encoding output: $revInt.n";
    echo "mb_strrev with encoding $enc output: $revEnc.n";

} else {
    echo "nCould not set internal encoding to $enc!n";
}
10
demandé sur OIS 2009-01-12 05:13:52

6 réponses

les fonctions Grapheme gèrent la chaîne UTF-8 Plus correctement que les fonctions mbstring et PCRE/ Mbstring et PCRE peuvent casser les caractères. Vous pouvez voir la différence entre eux en exécutant le code suivant.

function str_to_array($string)
{
    $length = grapheme_strlen($string);
    $ret = [];

    for ($i = 0; $i < $length; $i += 1) {

        $ret[] = grapheme_substr($string, $i, 1);
    }

    return $ret;
}

function str_to_array2($string)
{
    $length = mb_strlen($string, "UTF-8");
    $ret = [];

    for ($i = 0; $i < $length; $i += 1) {

    $ret[] = mb_substr($string, $i, 1, "UTF-8");
}

    return $ret;
}

function str_to_array3($string)
{
    return preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
}

function utf8_strrev($string)
{
    return implode(array_reverse(str_to_array($string)));
}

function utf8_strrev2($string)
{
    return implode(array_reverse(str_to_array2($string)));
}

function utf8_strrev3($string)
{
    return implode(array_reverse(str_to_array3($string)));
}

// http://www.php.net/manual/en/function.grapheme-strlen.php
$string = "a\xCC\x8A"  // 'LATIN SMALL LETTER A WITH RING ABOVE' (U+00E5)
         ."o\xCC\x88"; // 'LATIN SMALL LETTER O WITH DIAERESIS'  (U+00F6)

var_dump(array_map(function($elem) { return strtoupper(bin2hex($elem)); },
[
  'should be' => "o\xCC\x88"."a\xCC\x8A",
  'grapheme' => utf8_strrev($string),
  'mbstring' => utf8_strrev2($string),
  'pcre' => utf8_strrev3($string)
]));

Le résultat est là.

array(4) {
  ["should be"]=>
  string(12) "6FCC8861CC8A"
  ["grapheme"]=>
  string(12) "6FCC8861CC8A"
  ["mbstring"]=>
  string(12) "CC886FCC8A61"
  ["pcre"]=>
  string(12) "CC886FCC8A61"
}

IntlBreakIterator peut être utilisé depuis PHP 5.5 (intl 3.0);

function utf8_strrev($str)
{
    $it = IntlBreakIterator::createCodePointInstance();
    $it->setText($str);

    $ret = '';
    $pos = 0;
    $prev = 0;

    foreach ($it as $pos) {
        $ret = substr($str, $prev, $pos - $prev) . $ret;
        $prev = $pos;
    }

    return $ret;  
}
4
répondu masakielastic 2013-10-28 03:59:00

voici une autre approche utilisant regex:

function utf8_strrev($str){
 preg_match_all('/./us', $str, $ar);
 return implode(array_reverse($ar[0]));
}
8
répondu Fixtree 2010-09-20 07:55:48

voici un autre moyen. Cela semble fonctionner sans avoir à spécifier un encodage de sortie (testé avec un couple de différentes mb_internal_encoding s):

function mb_strrev($text)
{
    return join('', array_reverse(
        preg_split('~~u', $text, -1, PREG_SPLIT_NO_EMPTY)
    ));
}
6
répondu searlea 2009-08-26 22:32:26

La réponse

function mb_strrev($text, $encoding = null)
{
    $funcParams = array($text);
    if ($encoding !== null)
        $funcParams[] = $encoding;
    $length = call_user_func_array('mb_strlen', $funcParams);

    $output = '';
    $funcParams = array($text, $length, 1);
    if ($encoding !== null)
        $funcParams[] = $encoding;
    while ($funcParams[1]--) {
         $output .= call_user_func_array('mb_substr', $funcParams);
    }
    return $output;
}
4
répondu OIS 2009-01-12 02:14:09

une Autre méthode:

function mb_strrev($str, $enc = null) {
    if(is_null($enc)) $enc = mb_internal_encoding();
    $str = mb_convert_encoding($str, 'UTF-16BE', $enc);
    return mb_convert_encoding(strrev($str), $enc, 'UTF-16LE');
}
1
répondu Rob 2012-09-21 07:00:01

Il est facile utf8_strrev( $str ). Voir le source code de Ma bibliothèque que j'ai copié ci-dessous:

function utf8_strrev( $str )
{
    return implode( array_reverse( utf8_split( $str ) ) );
}

function utf8_split( $str , $split_length = 1 )
{
    $str    = ( string ) $str;

    $ret    = array( );

    if( pcre_utf8_support( ) )
    {
        $str    = utf8_clean( $str );

        $ret    = preg_split('/(?<!^)(?!$)/u', $str );

        // \X is buggy in many recent versions of PHP
        //preg_match_all( '/\X/u' , $str , $ret );
        //$ret  = $ret[0];
    }
    else
    {
        //Fallback

        $len    = strlen( $str );

        for( $i = 0 ; $i < $len ; $i++ )
        {
            if( ( $str[$i] & "\x80" ) === "\x00" )
            {
                $ret[]  = $str[$i];
            }
            else if( ( ( $str[$i] & "\xE0" ) === "\xC0" ) && ( isset( $str[$i+1] ) ) )
            {
                if( ( $str[$i+1] & "\xC0" ) === "\x80" )
                {
                    $ret[]  = $str[$i] . $str[$i+1];

                    $i++;
                }
            }
            else if( ( ( $str[$i] & "\xF0" ) === "\xE0" ) && ( isset( $str[$i+2] ) ) )
            {
                if( ( ( $str[$i+1] & "\xC0" ) === "\x80" ) && ( ( $str[$i+2] & "\xC0" ) === "\x80" ) )
                {
                    $ret[]  = $str[$i] . $str[$i+1] . $str[$i+2];

                    $i  = $i + 2;
                }
            }
            else if( ( ( $str[$i] & "\xF8" ) === "\xF0" ) && ( isset( $str[$i+3] ) ) )
            {
                if( ( ( $str[$i+1] & "\xC0" ) === "\x80" ) && ( ( $str[$i+2] & "\xC0" ) === "\x80" ) && ( ( $str[$i+3] & "\xC0" ) === "\x80" ) )
                {
                    $ret[]  = $str[$i] . $str[$i+1] . $str[$i+2] . $str[$i+3];

                    $i  = $i + 3;
                }
            }
        }
    }


    if( $split_length > 1 )
    {
        $ret = array_chunk( $ret , $split_length );

        $ret    = array_map( 'implode' , $ret );
    }

    if( $ret[0] === '' )
    {
        return array( );
    }

    return $ret;
}


function utf8_clean( $str , $remove_bom = false )
{
    $regx = '/([\x00-\x7F]|[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3})|./s';

    $str    = preg_replace( $regx , '' , $str );

    if( $remove_bom )
    {
        $str    = utf8_str_replace( utf8_bom( ) , '' , $str );
    }

    return $str;
}


function utf8_str_replace( $search , $replace , $subject , &$count = 0 )
{
    return str_replace( $search , $replace , $subject , $count );
}


function utf8_bom( )
{
    return "\xef\xbb\xbf";

}


function pcre_utf8_support( )
{
    static $support;

    if( !isset( $support ) )
    {
        $support = @preg_match( '//u', '' );
        //Cached the response
    }

    return $support;
}
0
répondu Hamid Sarfraz 2013-11-03 20:11:23