Заменить на месте, синтаксический анализ и манипулирование строк - PullRequest
0 голосов
/ 23 марта 2010

Я пытаюсь заменить набор символов в строке. Строка может иметь или не иметь какие-либо данные для изменения. Строка размечена таким образом, чтобы она могла менять свой цвет из набора символов. Строка может сбросить форматирование по умолчанию, используя определенный набор символов.

Эта установка очень похожа на стандарт ECMA-48, используемый на консолях LINUX для цветов и других специальных эффектов.

Где одна строка может быть ^0Black^1Red^2Green^3Yellow^4Blue^5Purple^6Cyan^7White Создание следующего HTML:

<span style="color: #000">Black</span><span style="color: #F00">Red</span><span style="color: #0F0">Green</span><span style="color: #FF0">Yellow</span><span style="color: #00F">Blue</span><span style="color: #F0F">Purple</span><span style="color: #0FF">Cyan</span><span style="color: #FFF">White</span>

Другая строка (^1Error^8: ^3User Error) также может выдавать:

<span style="color: #F00">Error</span>: <span style="color: #FF0">User Error</span>

Возможно, вы заметили, что ^8 часть этой строки сбрасывает цвет для этой части строки.

Каков наилучший способ анализа этих строк?

Ответы [ 2 ]

3 голосов
/ 23 марта 2010

Я бы использовал preg_replace_callback . Поскольку при обратном вызове требуются дополнительные данные, было бы целесообразно собрать их все вместе в одном классе, например:

class Escaper
{
    function __construct() {
        $this->colors = array(
            0 => "#000",
            1 => "#00F", 
            //etc
        );
    }

    function replace_color($m) {
        list(, $color, $text) = $m;
        return isset($this->colors[$color]) ?
            "<span style='color:{$this->colors[$color]}'>{$text}</span>" :
            $text;
    }

    function apply($text) {
        $text = preg_replace_callback('~\^(\d+)([^^]+)~', array($this, 'replace_color'), $text);
        // more escapes to process?

        return $text;
    }
}

//

 $e = new Escaper; 
 $convertedText = $e->apply($sourceText);
0 голосов
/ 30 марта 2010

Я создал функцию str_inject следующим образом:

<?php

/* Function Calls */
// Inject one string into another at a specific point.
function str_inject($sourceStr, $injectStr, $injectPos)
{
    if ($injectPos >= strlen($sourceStr)) {
        trigger_error('Inject posisition is greater then the length of the source string, concating string!', E_USER_NOTICE);
        return str_pad($sourceStr, $injectPos) . $injectStr;
    }

    return substr($sourceStr, 0, $injectPos) . $injectStr . substr($sourceStr, $injectPos);
}

/* Example Strings */
#        0123456789012345
$str1 = 'This is a string';
$str2 = ' just';

/* Example Output */
// Example 1: Proper Useage.
$str = str_inject($str1, $str2, 7);
echo $str . PHP_EOL; # echos: 'This is just a string';

// Example 2: Inproper Useage.
$str = str_inject($str1, $str2, 16);
echo $str . PHP_EOL; # echos: 'This is a string just';

// Example 3: Non Hidden, Short Hand, ECMA-48 Colours
# Make ECMA-48 of Strings.
$ecma48 = array();
for ($i = 0; $i < 8; ++$i)
{
    $ecma48[$i] = "\033[3{$i}m";
}
$ecma48[] = "\033[39m"; # Reset Forground Color
$ecma48[] = "\033[0m"; # Reset All

# Setting up Varables
$str = '^1Red^8Reset Color'; # Example String

# Parse str loop
for ($i = 0, $j = 1, $l = strlen($str); $i < $l; ++$i, ++$j)
{
    if ($str{$i} == '^' && is_numeric($str{$j}))
    {
        // Save Δ Change Array Key Number & Δ Len of Replace Str;
        $ΔAKN = $str[$j]; # Δ (Change) Array Key Number;
        $ΔLen = strlen($ecma48[$ΔAKN]); # Δ (Change) Array Value Len. 
        // Remove The Formatting
        $str[$i] = NULL; # Remove ^
        $str[$j] = NULL; # Remove Int.
        // Place ECMA-48 Charaters into String.
        $str = str_inject($str, $ecma48[$ΔAKN], $i);
        // Move Str Pointers Past Δ.
        $i += $ΔLen;
        $j += $ΔLen;
        // And Increase String Size to New Length.
        $l += $ΔLen - 2; # Minus two because we removed the formatting already.
    }
}

# Print results.
echo $str;

?>
...