【问题标题】:Mirc control codes to html, through phpMirc控制代码转为html,通过php
【发布时间】:2012-05-06 22:49:27
【问题描述】:

我意识到以前在这个论坛上也有人问过这个问题,但建议的解决方案对我来说并不可靠。

到目前为止,我已经为此工作了一周或更长时间,昨天我一直熬夜到凌晨 3 点……但我跑题了,让我谈谈手头的问题:

对于那些不知道的人,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 更可靠,但发送到服务器的数据呈指数增长,以至于套接字在上传时超时,所以它不是一个可行的选择。

与往常一样,我们将不胜感激。

【问题讨论】:

    标签: php html regex preg-replace mirc


    【解决方案1】:

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

    $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() 函数将在当前偏移量处查找令牌,如果找到,将推进偏移量并返回令牌,包括。所有子组匹配。由于涉及到偏移,更详细的$matches 数组被简化(移除了偏移),因为主程序通常不需要知道偏移。

    这里的原则很简单:第一个模式获胜。因此,您需要将最匹配的模式(在字符串长度的意义上)放在顶部以使其正常工作。在您的情况下,最大的一个是前景色和背景色的标记,&lt;color-fgbg&gt;

    如果找不到token,则返回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.

    相关资源:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-07
      • 2019-05-28
      相关资源
      最近更新 更多