2012-04-26 1 views
1

나는 이것이 매우 적은 포럼에서 이전에 물어 왔다는 것을 알고 있지만, 제안 된 해결책은 나를 신뢰할 만하지 않았다. 들어mirc 제어 코드, PHP를 통해

:

내가 일주일 동안이 작업 또는 지금보다, 나는이 작업을 어제 오전 3시까지 '까지 있었다 ... 그러나 나는 탈선 한, 내가 손에 문제에 도착하자 인식하지 못하는 mirc는 문자 색, 밑줄, 무게 및 이탤릭체를 제어하기 위해 ASCII 코드를 사용합니다. 색상의 ASCII 코드는 3, 굵게 2, 밑줄 1F, 기울임 꼴 1D 및 반전 (검정색 바탕에 흰색 텍스트)입니다.

이 데이터가 들어올 형태의 예로서 (문자가 인쇄되지 않으므로 정규 표현식에서) :

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

등 - 기타.

다음은 내가 직접 사용하려고 수정 한 두 기능이지만 신뢰할 수없는 결과를 반환했습니다. 그 코드에 들어가기 전에, '신뢰할 수 없다'라는 것을 구체적으로 표현하기 위해, 때때로 코드가 해석 될 것이고, 다른 때에도 여전히 텍스트에 제어 코드가 남아있을 것이고, 나는 그 이유를 알 수 없습니다. 어쨌든;

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

출처 : : 코드가 호출이 관련된 경우

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>'; 
} 

그리고, First을, 나는 물론했습니다 Second

또한 수행 방법을보고 시도 다양한 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() 함수는 현재 오프셋에서 토큰을 찾고 오프셋이 발견되면 토큰을 반환합니다.모든 하위 그룹이 일치합니다. 오프셋과 관련하여, 메인 루틴은 일반적으로 오프셋에 대해 알 필요가 없기 때문에보다 상세한 $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과 다른 something)을 변경하는 것이 더 쉬울뿐만 아니라 장래에 새로운 코드를 지원할 수있게됩니다. 또한 무언가가 누락 된 경우 인식되지 않은 코드 또는 변환에 누락 된 코드이기 때문에 더 쉽게 문제를 해결할 수 있습니다.

요지로 전체 예 : Tokenizer Example of Mirc Color and Style (bold) Codes.

관련 리소스 :

+0

글쎄, 나는 마침내 정말로 뭔가 콘크리트가 나타납니다 벗어났다. 불행히도 나를 위해 2:40에 곧있을 것이지만, 이것에 대해 다시 한번 감사드립니다. 나는 내일이 일을해야 할 것이다. 그러나 다시 도움을 주셔서 감사합니다. – Daedalus