2017-08-26 81 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

相关问题