2012-04-26 68 views
1

我意识到这已被问及之前,在这个非常论坛上,但提出的解决方案对我来说并不可靠。Mirc控制代码到html,通过php

我一直在这一个星期或更多,现在,我昨天熬夜”,直到凌晨三时它的工作...但我离题了,让我对这个问题的另一方面:

对于那些不知道的,mirc使用ascii控制代码来控制字符颜色,下划线,重量和斜体。颜色的ascii代码是3,粗体2,下划线1F,斜体1D和反向(黑底白字)16。 (在正则表达式中,因为那些字符不会打印):

\x034this text is red\x033this text is green\x03 \x02bold text\x02 
\x034,3this text is red with a green background\x03 

等等。

下面是我尝试修改自己使用的两个函数,但返回了不可靠的结果。在进入代码之前,为了具体说明'不可靠',有时代码会解析,其他时候仍然会有控制代码留在文本中,我不知道为什么。无论如何;

function mirc2html($x) { 
    $c = array("FFF","000","00007F","009000","FF0000","7F0000","9F009F","FF7F00","FFFF00","00F800","00908F","00FFFF","0000FF","FF00FF","7F7F7F","CFD0CF"); 
    $x = preg_replace("/\x02(.*?)((?=\x02)\x02|$)/", "<b>$1</b>", $x); 
    $x = preg_replace("/\x1F(.*?)((?=\x1F)\x1F|$)/", "<u>$1</u>", $x); 
    $x = preg_replace("/\x1D(.*?)((?=\x1D)\x1D|$)/", "<i>$1</i>", $x); 
    $x = preg_replace("/\x03(\d\d?),(\d\d?)(.*?)(?(?=\x03)|$)/e", "'</span><span style=\"color: #'.\$c[$1].'; background-color: #'.\$c[$2].';\">$3</span>'", $x); 
    $x = preg_replace("/\x03(\d\d?)(.*?)(?(?=\x03)|$)/e", "'</span><span style=\"color: #'.\$c[$1].';\">$2</span>'", $x); 
    //$x = preg_replace("/(\x0F|\x03)(.*?)/", "<span style=\"color: #000; background-color: #FFF;\">$2</span>", $x); 
    //$x = preg_replace("/\x16(.*?)/", "<span style=\"color: #FFF; background-color: #000;\">$1</span>", $x); 
    //$x = preg_replace("/\<\/span\>/","",$x,1); 
    //$x = preg_replace("/(\<\/span\>){2}/","</span>",$x); 
    return $x; 
} 

function color_rep($matches) { 
    $matches[2] = ltrim($matches[2], "0"); 
    $bindings = array(0=>'white',1=>'black',2=>'blue',3=>'green',4=>'red',5=>'brown',6=>'purple',7=>'orange',8=>'yellow',9=>'lightgreen',10=>'#00908F', 
     11=>'lightblue',12=>'blue',13=>'pink',14=>'grey',15=>'lightgrey'); 
    $preg = preg_match_all('/(\d\d?),(\d\d?)/',$matches[2], $col_arr); 
    //print_r($col_arr); 
    $fg = isset($bindings[$matches[2]]) ? $bindings[$matches[2]] : 'transparent'; 
    if ($preg == 1) { 
     $fg = $bindings[$col_arr[1][0]]; 
     $bg = $bindings[$col_arr[2][0]]; 
    } 
    else { 
     $bg = 'transparent'; 
    } 


    return '<span style="color: '.$fg.'; background: '.$bg.';">'.$matches[3].'</span>'; 
} 

而且,如果它是相关的,其中代码被称为:

$logln = preg_replace_callback("/(\x03)(\d\d?,\d\d?|\d\d?)(\s?.*?)(?(?=\x03)|$)/","color_rep",$logln); 

来源:FirstSecond

我有,当然也尝试一下做方法通过各种基于php/ajax的irc客户端,并且在那里没有任何成功。至于做这个mirc端,我也在那里查看,虽然结果比php更可靠,但发送到服务器的数据会以指数方式增长,直到套接字超出上传时间,所以它不是'这是一个可行的选择。

一如既往,任何有关此事的帮助将不胜感激。

回答

3

你应该分解问题,例如用分词器。标记器将扫描输入字符串并将特殊部分转换为命名标记,所以脚本的其余部分可以标识它们。用例:

$mirc = "\x034this text is red\x033this text is green\x03 \x02bold text\x02 
\x034,3this text is red with a green background\x03"; 

$tokenizer = new Tokenizer($mirc); 

while(list($token, $data) = $tokenizer->getNext()) 
{ 
    switch($token) 
    { 
     case 'color-fgbg': 
      printf('<%s:%d,%d>', $token, $data[1], $data[2]); 
      break; 

     case 'color-fg': 
      printf('<%s:%d>', $token, $data[1]); 
      break; 

     case 'color-reset': 
     case 'style-bold'; 
      printf('<%s>', $token); 
      break; 

     case 'catch-all': 
      echo $data[0]; 
      break; 

     default: 
      throw new Exception(sprintf('Unknown token <%s>.', $token)); 
    } 
} 

这并不多还,但识别有趣的部分和他们(子)值作为输出演示:

<color-fg:4>this text is red<color-fg:3>this text is green<color-reset> <style-bold>bold text<style-bold> 
<color-fgbg:4,3>this text is red with a green background<color-reset> 

它应该是比较容易为你修改循环以上,并处理状态,如打开/关闭颜色和字体变量标签,如粗体。

标记器本身定义了一组标记,它试图在某个偏移处(从字符串的开始处开始)逐个找到它们。该令牌是由正则表达式定义:

/** 
* regular expression based tokenizer, 
* first token wins. 
*/ 
class Tokenizer 
{ 
    private $subject; 
    private $offset = 0; 
    private $tokens = array(
     'color-fgbg' => '\x03(\d{1,2}),(\d{1,2})', 
     'color-fg' => '\x03(\d{1,2})', 
     'color-reset' => '\x03', 
     'style-bold' => '\x02', 
     'catch-all' => '.|\n', 
    ); 
    public function __construct($subject) 
    { 
     $this->subject = (string) $subject; 
    } 
    ... 

由于这种专有阵列显示,简单的正则表达式和他们得到与他们的键的名称。这是上述switch声明中使用的名称。

next()函数将在当前偏移量处查找令牌,并且如果找到该值,则会提前偏移量并返回令牌incl。所有小组匹配。由于涉及偏移量,所以更详细的$matches阵列被简化(去除了偏移量),因为主程序通常不需要知道偏移量。

原理很简单:第一种模式获胜。所以你需要把最匹配的模式(以字符串长度的意思)放在最上面以使其工作。在你的情况下,最大的一个是前景色和背景色的标记,<color-fgbg>

如果没有令牌可以发现,NULL返回,所以这里的next()功能:

... 
/** 
* @return array|null 
*/ 
public function getNext() 
{ 
    if ($this->offset >= strlen($this->subject)) 
     return NULL; 

    foreach($this->tokens as $name => $token) 
    { 
     if (FALSE === $r = preg_match("~$token~", $this->subject, $matches, PREG_OFFSET_CAPTURE, $this->offset)) 
      throw new RuntimeException('Pattern for token %s failed (regex error).', $name); 
     if ($r === 0) 
      continue; 
     if (!isset($matches[0])) { 
      var_dump(substr($this->subject, $this->offset)); 
      $c = 1; 
     } 
     if ($matches[0][1] !== $this->offset) 
      continue; 
     $data = array(); 
     foreach($matches as $match) 
     { 
      list($data[]) = $match; 
     } 

     $this->offset += strlen($data[0]); 
     return array($name, $data); 
    } 
    return NULL; 
} 
... 

因此字符串的标记化现在被封装到Tokenizer类和令牌的解析是什么你可以在你的应用程序的其他部分内部做你自己的事情。这会让你更容易改变样式的方式(HTML输出,基于CSS的HTML输出或类似bbcode或markdown的东西),而且还可以支持未来的新代码。此外,如果缺少某些东西,您可以更轻松地解决问题,因为它可能是未经认可的代码或缺少转换。

完整的例子作为依据:Tokenizer Example of Mirc Color and Style (bold) Codes.

相关资源:

+0

嗯,看来我终于有一些具体的真正离开。再次感谢你,虽然不幸的是,我很快就要到凌晨2点40分了。明天我必须开始工作。但是,再次感谢您的帮助。 – Daedalus 2012-04-26 09:39:17