1

これは、まさにこのフォーラムで以前に質問されたことに気づきましたが、提案された解決策は私にとって信頼できるものではありませんでした。

私はこれに1週間以上取り組んでおり、昨日の午前3時まで起きていました.

ご存じない方のために説明すると、mirc は 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

など。

以下は、私が自分で使用するために変更を試みたが、信頼できない結果を返した 2 つの関数です。そのコードに入る前に、具体的に「信頼できない」と言うと、コードが解析されることもあれば、テキストにまだ制御コードが残っていることもあり、その理由がわかりません。ともかく;

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);

ソース:ファーストセカンド

もちろん、さまざまな php/ajax ベースの irc クライアントによって実行されるメソッドも調べてみましたが、成功していません。この mirc-side を行うことに関しては、私もそこを見てきました。結果は php よりも信頼性が高いものの、サーバーに送信されるデータが指数関数的に増加し、ソケットがアップロード時にタイムアウトになるので、そうではありません。実行可能なオプションです。

いつものように、この問題の助けをいただければ幸いです。

4

1 に答える 1

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()関数は現在のオフセットでトークンを探し、見つかった場合はオフセットを進めてトークンを返します。すべてのサブグループの一致。$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.

関連リソース:

于 2012-04-26T09:13:21.827 に答える