【问题标题】:Regex, extract single value from html encoded string正则表达式,从 html 编码字符串中提取单个值
【发布时间】:2011-11-08 21:28:51
【问题描述】:

我无法提取某些值,这是我的表达方式:

flag:(\S+)=\&quot\;?((?:.(?!\&quot?\s+(?:\S+)=|">))+.)\&quot\;?

它只是试图从一个 html 编码的字符串中提取值。

这是一个运行良好的示例。

<p class="text1" target="701_text" flag:text1="This is a test">

为第二次() 捕获返回此值,这是正确的:This is a test

但是,单个值似乎返回第一个字符,加上第一个 ";

<p class="text1" target="701_text" flag:text1="T">

返回:;T 而不仅仅是 T,这是我需要它做的。

我只需要修改表达式以允许单个值同时仍然正确返回多个值。

【问题讨论】:

    标签: php regex


    【解决方案1】:

    我认为这就是您想要的正则表达式:

    flag:(\S+)="((?:.(?!"(?:\S+)=|">))*.?)"
    

    请注意,您不需要逃避那么多。 &; 不是特殊字符,因此不需要转义。此外,HTML 实体总是以分号结尾,否则它们是无效的,因此您在 ; 之后的所有问号都是不需要的(或者说是有害的)。

    那么你的表达式的实际问题如下:对" 具有否定前瞻的内部组预期有1 个或多个匹配项(因为+)。在 T 作为单个文本的情况下,T 之后已经被 . 占用(正确地需要匹配负前瞻确实适用的最后一个字符)。现在没有剩余的字符可以实际匹配前瞻表达式(尽管它需要一个匹配)。那么正则表达式做了什么?它采用了标记为可选的分号(因为?)并将其拉入捕获组。这样就解释了分号的来源。

    如果您按照上面的建议删除分号后的问号,那么您会遇到正则表达式与 T 根本不匹配的问题(因为它需要两个或更多字符)。所以解决方案是不允许任何字符匹配否定的前瞻表达式(即* 而不是+)。然后,如果你想让正则表达式更好,可以通过在最后的. 中添加? 来允许引号内的空序列。然后你应该有一个工作表达式。

    当然,鉴于这是使用 HTML 实体编码的,最好先简单地解码这些实体,然后直接匹配引号,正如 Matteo 建议的那样。这个答案只是为了解释你的表达有什么问题:)

    【讨论】:

      【解决方案2】:

      您为什么不先对其进行解码并处理该版本的字符串?如果我了解您的要求,您可以试试这个:

      $str = '<p class="text1" target="701_text" flag:text1="T">';
      
      $decoded = html_entity_decode($str);
      
      preg_match('/flag:(.+?)="(.+?)"/', $decoded, $match);
      
      print_r($match);
      

      【讨论】:

      • 看起来可以这样做,我已经添加了 (.*)= reloaded 并且看到您也更改了它。 ;) 感谢您的回复。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-25
      • 1970-01-01
      • 2020-07-13
      • 2021-05-24
      相关资源
      最近更新 更多