Replace in place, parsing & string manipulation
I'm trying to replace a set of characters within a string. The string may or may not have any data to change. The string is marked up in a way that allows for it to change it's color from a set of characters. The string can reset it's formatting to default by using a defined set of characters.
This setup is very much like the ECMA-48 standard used on LINUX consoles for colors and other special effects.
Where one string could be ^0Black^1Red^2Green^3Yellow^4Blue^5Purple^6Cyan^7White
Producing the following HTML:
<span style="color: #000">Black</span><span style="color: #F00">Red</开发者_StackOverflow中文版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>
Another string (^1Error^8: ^3User Error
) could also produce:
<span style="color: #F00">Error</span>: <span style="color: #FF0">User Error</span>
You might of noticed the ^8
part of that string resets the color for that part of the string.
What's the best way to go about parsing these kinds of strings?
I'd use preg_replace_callback. Since there is additional data required in the callback, it would be practical to put it all together in a class, like this:
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);
I created the str_inject function, as follows:
<?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;
?>
精彩评论