2017-08-26 112 views
-1

我有這樣的HTML:正則表達式替換文本之外的腳本標籤

 
"This is simple html text <script language="javascript">simple simple text text</script> text" 

我只需匹配了外部的腳本標籤的話。我的意思是,如果我想匹配「簡單」和「文本」,我應該只從「這是簡單的HTML文本」和最後一部分「文本」得到結果 - 結果將是「簡單」1匹配,「文本」2火柴。任何人都可以幫助我嗎?我使用PHP。

我找到了比賽的文字了類似的回答標籤外:

(text|simple)(?![^<]*>|[^<>]*</) 

Regex replace text outside html tags

但couln't投入到一個特定的標籤(腳本)工作:

(text|simple)(?!(^<script*>)|[^<>]*</) 

ps:這個問題不是重複的(strip_tags, remove javascript)。因爲我不想去掉標籤,或者選擇腳本標籤內的內容。我試圖替換標籤「腳本」之外的內容。

+0

你絕對需要匹配,或捕獲組會做什麼? – Vivick

+0

如果您想自信地解析html,請使用不是正則表達式的html解析器。所以反覆說這一遍又一遍。 IIRC甚至有一個說明,即SO軟件彈出說「不要使用正則表達式來解析html」。 – mickmackusa

+0

@mickmackusa,但是當你使用解析器時,他們停止工作,解析格式錯誤的html。 我覺得這個問題不是重複的。因爲我沒有試圖剝離標籤,我試圖替換標籤「腳本」之外的內容。 –

回答

1

我的模式將使用(*SKIP)(*FAIL)取消其參賽資格匹配的腳本標記及其內容。

textsimple將在每次符合條件時匹配。

正則表達式:~<script.*?/script>(*SKIP)(*FAIL)|text|simple~

Pattern/Replacement Demo Link

代碼:(Demo

$strings=['This has no replacements', 
    'This simple text has no script tag', 
    'This simple text ends with a script tag <script language="javascript">simple simple text text</script>', 
    'This is simple html text is split by a script tag <script language="javascript">simple simple text text</script> text', 
    '<script language="javascript">simple simple text text</script> this text starts with a script tag' 
]; 

$strings=preg_replace('~<script.*?/script>(*SKIP)(*FAIL)|text|simple~','***replaced***',$strings); 

var_export($strings); 

輸出:

array (
    0 => 'This has no replacements', 
    1 => 'This ***replaced*** ***replaced*** has no script tag', 
    2 => 'This ***replaced*** ***replaced*** ends with a script tag <script language="javascript">simple simple text text</script>', 
    3 => 'This is ***replaced*** html ***replaced*** is split by a script tag <script language="javascript">simple simple text text</script> ***replaced***', 
    4 => '<script language="javascript">simple simple text text</script> this ***replaced*** starts with a script tag', 
) 
0

如果它保證script會存在,那麼簡單地

(.*?)<script.*</script>(.*) 

以外的標記文本匹配將出現在子匹配1和2。如果script是可選然後做(.*?)(<script.*</script>)?(.*)

0

這裏是另一種解決方案

([\w\s]*)(?:<script.*?\/script>)(.*)$ 

這裏是https://regex101.com/r/1Lthi8/1

+0

我試圖替換標記之外的字符串。 –

+0

是的,這是在第1組中捕獲的,因爲regex101突出顯示'這是簡單的html文本' – JBone

+0

匹配2位於標記內,最後一個單詞「text」未被選中。 最後,這是試圖忽略所有的標籤,而不是特定的標籤「腳本」。 –

0

演示只是一個供參考,至於標籤去,這是不可忽視的一個標籤
沒有解析所有標籤。

您可以跳過/失敗過去的html標籤和隱形內容。
這會找到你要找的單詞。

'~<(?:(?:(?:(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)(?!)|(?:text|simple)~'

https://regex101.com/r/7ZGlvW/1

格式化

< 
    (?: 
     (?: 
       (?: 
               # Invisible content; end tag req'd 
        (       # (1 start) 
         script 
        | style 
        | 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]*?) 
      ) 
     ) 
    ) 
    > 
    (*SKIP) 
    (?!) 
| 
    (?: text | simple) 

或者,更快的方法是符合這兩個標籤文本你
尋找。

將標籤匹配移過它們。

如果您正在進行替換,請使用回調來確定要替換的內容。
組1是TAG隱形內容運行
第3組是你正在取代的詞。

因此,在回調中,如果組1匹配,只需返回組1.如果組3匹配,則替換爲您想要替換的組。

正則表達式

'~(<(?:(?:(?:(script|style|object|embed|applet|noframes|noscript|noembed)(?:\s+(?>"[\S\s]*?"|\'[\S\s]*?\'|(?:(?!/>)[^>])?)+)?\s*>)[\S\s]*?</\2\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]*?))))>)|(text|simple)~'

https://regex101.com/r/7ZGlvW/2


這正則表達式是媲美SAX和DOM解析器解析如何標記。
我已經在SO上發佈了數百次。

下面是如何刪除所有的HTML標籤的例子:

https://regex101.com/r/oCVkZv/1

+0

此regEx正常工作,但使用大量內存,導致錯誤: Firefox:連接已重置 Chrome:(net :: ERR_CONNECTION_RESET):連接已重置。 IE瀏覽器:Internet Explorer無法顯示網頁 –

+0

@PauloACosta - 我發現您已接受我最初發布的_skip/fail_回答。但是,正如我所說的'不可能忽略單個標籤 而不解析所有標籤'。用我的正則表達式_will_跳過/失敗會更慢。從哪裏得到_MEMORY_問題不是來自正則表達式。否則,爲了速度,我說_不要使用跳過/失敗,而只是使用我以後的正則表達式來匹配你需要的標籤和文本。你在答案中做出了錯誤的選擇。這太糟糕了... – sln

相關問題