2017-03-09 57 views
1

我正在PHP中開發一個Telegram Bot,我必須處理字符串,其中只有一些basic HTML tag are allowed和所有<,>&符號不是標記或HTML的一部分實體必須與相應的HTML實體(<&lt;>&gt;&&amp;
例字符串PHP正則表達式負面lookbehind可變長度的替代方案問題

<b>bold</b>, <strong>bold</strong> 
<i>italic</i>, <em>italic</em> 
<a href="http://www.example.com/" >inline URL</a> 
<code>inline fixed-width code</code> 
<pre>pre-formatted fixed-width code block</pre> 
yes<b bad<>b> <bad& hi>;<strong >b<a< 

我設法取代被替換0和<通過使用正則表達式。例如,我在這種模式<(?!(?:(?:\/?)(?:(?:b>)|(?:strong>)|(?:i>)|(?:em>)|(?:code>)|(?:pre>)|(?:a(?:[^>]+?)?>))))中使用負向視圖來擺脫<符號。

但我無法建立一個模式來取代>符號,它不是任何標籤的一部分。 PCRE不支持不確定的量詞。雖然它允許lookbehinds內部的替代品具有不同的長度,但要求每個替代品具有固定的長度。

所以,我試圖用這種模式(仍然是不完整)(?<!(?:(?:<b)|(?:<strong)|(?:<i)|(?:<em)|(?:<code)|(?:<pre>)|(?:<a)))>在所有的選擇都有固定的長度,但它仍然說Compilation failed: lookbehind assertion is not fixed length

+0

是會爲亞朋友做一個很好的答案。離開,迴歸一個好的正則表達式解決方案,但看到你已經標記了一個短暫的正則表達式解決方案,永遠不會工作。不幸的是,我無法抹去我的答案。當我看到你的名字時,我會更好地知道。 – sln

回答

1

正確的答案是使用DOM解析器來代替。雖然對於一個快速和骯髒的(有時更快)的方式,你可以使用(*SKIP)(*FAIL)機制PCRE工具:

<[^<>&]+>(*SKIP)(*FAIL)|[<>&]+ 

a demo on regex101.com


完整 PHP步行通過的將是:

<?php 
$string = <<<DATA 
<b>bold</b>, <strong>bold</strong> 
<i>italic</i>, <em>italic</em> 
<a href="http://www.example.com/" >inline URL</a> 
<code>inline fixed-width code</code> 
<pre>pre-formatted fixed-width code block</pre> 
yes<b bad<>b> <bad& hi>;<strong >b<a< 
DATA; 

$regex = '~<[^<>&]+>(*SKIP)(*FAIL)|[<>&]+~'; 
$string = preg_replace_callback($regex, 
    function($match) { 
     return htmlentities($match[0]); 
    }, 
    $string); 

echo $string; 
?> 

其中產量:

<b>bold</b>, <strong>bold</strong> 
<i>italic</i>, <em>italic</em> 
<a href="http://www.example.com/" >inline URL</a> 
<code>inline fixed-width code</code> 
<pre>pre-formatted fixed-width code block</pre> 
yes&lt;b bad&lt;&gt;b&gt; &lt;bad&amp; hi&gt;;<strong >b&lt;a&lt; 

然而,由於在計算器上多次表示之前,請考慮使用一個解析器來代替,畢竟這是他們是爲了。


解析器的方式可以是:

$dom = new DOMDocument(); 
$dom->loadHTML($string, LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR); 

echo $dom->saveHTML(); 

但是,你提出的片段是如此敗壞的正則表達式可能是處理它的唯一途徑。

+0

謝謝你的回答。我確實嘗試過DOM解析器,但沒有得到理想的結果。你能告訴我我該怎麼做嗎? – ManzoorWani

+0

@ManzoorWani:已更新,請參閱答案的結尾。 – Jan

+0

是的,片段預計不會有效,這就是我尋找Regex的原因。無論如何,你給了這個想法如何用正則表達式來處理它。謝謝:) – ManzoorWani

1

你可以找到合法的特殊符號轉換爲這樣的實體。

最重要的是正確解析標籤。
免責聲明 - 如果你不這樣做,沒有理由甚至使用正則表達式,它不會工作。

在每場比賽,第0組將包含兩種<,>,或&
您可以添加更多的,請參閱正則表達式底部

正則表達式
(?:(?><(?:(?:(?:(script|style|object|embed|applet|noframes|noscript|noembed)(?:\s+(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+)?\s*>)[\S\s]*?</\1\s*(?=>))|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]?)+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>)(*SKIP)(*FAIL)|[<>]|[&](?!(?i:[a-z]+|(?:\#(?:[0-9]+|x[0-9a-f]+)));))

解釋

(?: 
     (?>       # Atomic group 
      <        # Match tag forms and fail them with skip/fail verbs (see below) 
      (?: 
       (?: 
        (?: 
                 # Invisible content; end tag req'd 
          (       # (1 start) 
           script 
          | style 
           #| head 
          | object 
          | embed 
          | applet 
          | noframes 
          | noscript 
          | noembed 
         )        # (1 end) 
          (?: 
           \s+ 
           (?> 
            " [\S\s]*? " 
           | ' [\S\s]*? ' 
           | (?: 
             (?! />) 
             [^>] 
            )? 
           )+ 
         )? 
          \s* > 
        ) 

        [\S\s]*? </ \1 \s* 
        (?= >) 
       ) 

      | (?: /? [\w:]+ \s* /?) 
      | (?: 
        [\w:]+ 
        \s+ 
        (?: 
          " [\S\s]*? " 
         | ' [\S\s]*? ' 
         | [^>]? 
        )+ 
        \s* /? 
       ) 
      | \? [\S\s]*? \? 
      | (?: 
        ! 
        (?: 
          (?: DOCTYPE [\S\s]*?) 
         | (?: \[CDATA\[ [\S\s]*? \]\]) 
         | (?: -- [\S\s]*? --) 
         | (?: ATTLIST [\S\s]*?) 
         | (?: ENTITY [\S\s]*?) 
         | (?: ELEMENT [\S\s]*?) 
        ) 
       ) 
      ) 
      > 
    )        # End atomic group 
     (*SKIP)(*FAIL) 

    |        #or, 
     [<>]       # Angle brackets 

    |        #or, 
     [&]       # Ampersand 
     (?!       # Only if not an entity 
      (?i: 
       [a-z]+ 
      | (?: 
        \# 
        (?: 
          [0-9]+ 
         | x [0-9a-f]+ 
        ) 
       ) 
      ) 
      ;  
    ) 

     # Add more here 
) 
相關問題