【问题标题】:Regular Expression to find a Tag (preg_replace_callback)正则表达式查找标签 (preg_replace_callback)
【发布时间】:2011-02-11 12:21:38
【问题描述】:

我需要为 WP-Plugin 找到所有出现的标签。

<wpg3>10|300|defaultTemplate|eyJhbGlnbiI6ImFsaWdubGVmdCJ9</wpg3>

标签 (,,, ...) 有多个可能的版本,但 start 和 end 匹配。组是可选的:应该意味着,可以没有或一个,或两个或三个“|”,它们分隔选项。

我的问题:如果我的搜索字符串中只有一个标签,一切都会按预期工作。 但是如果我在我的字符串中添加第二个标签,回调只会被调用一次,而不是每个标签一次。在开始或结束时必须缺少一些东西。 如果 last Argument (功能)丢失,则 Regexp 使用多个标签会失败。

  $return = preg_replace_callback('/<wpg[23](?P<unused>id)?>(?P<uri_or_id>[^\|]*)[\|]?(?P<width>[^\|]*)[\|]?(?P<template>[^\|]*)[\|]?(?P<features>[^\|]*)<\/wpg[23](?P<unused2>id)?>/i', array( $this, 'wpg3_content' ), $content );

我以上面的例子为例:

Array
(
    [0] => 10|300|defaultTemplate|eyJhbGlnbiI6ImFsaWdubGVmdCJ9
    [unused] =>
    [1] => 
    [uri_or_id] => 10
    [2] => 10
    [width] => 300
    [3] => 300
    [template] => defaultTemplate
    [4] => defaultTemplate
    [features] => eyJhbGlnbiI6ImFsaWdubGVmdCJ9
    [5] => eyJhbGlnbiI6ImFsaWdubGVmdCJ9
)

【问题讨论】:

  • | 分隔符之间可以没有值吗?通过标签,你的意思是&lt;wpg3&gt;,对吧?

标签: php regex html-parsing


【解决方案1】:

你能先在标签上做一个 preg_match_all

preg_match_all("/<([^>]*)?>/",$in, $out);

然后循环遍历 $out 数组,您应该在其中拥有标签名称和内容。

如果标签匹配你想要的那么

explode($out[2],"|")

或者你想在你的正则表达式中做所有事情?

【讨论】:

  • 基本上我做一个 : if(false === stripos($content, '
【解决方案2】:

一旦你回答了我上面的评论,我可能会有更准确的信息。这是我到目前为止所拥有的。我是用 Python 做的,因为它对我来说更容易,但你明白了。

这是我的正则表达式:

regex = re.compile('''
    <(?P<tag>wpg[23])(?P<unused>id)?>
   (?:
      (?P<uri_or_id>[^\|<]+)
       (?:
           \|(?P<width>[^\|<]+)
           (?:
              \|(?P<template>[^\|<]+)
              (?:
                 \|(?P<features>[^\|<]+)
               )?
            )?
        )?
    )?</(?P=tag)(?P<unused2>id)?>''', re.IGNORECASE|re.VERBOSE)

选项中的每个文本都是强制性的,但可选的不匹配组确保选项确实是可选的。我还使用后向表达式(?P=tag) 来确保结束标记与开始标记匹配。我用[^\|&gt;] 对匹配项的保护比[^\|] 多一点,以防止出现多标签问题。

我的测试字符串:

# Your example
>>> text
'<wpg3>10|300|defaultTemplate|eyJhbGlnbiI6ImFsaWdubGVmdCJ9</wpg3>'

# Options should be, well, optional
>>> text2
'<wpg3>10|300|defaultTemplate</wpg3>'

# These two should fail if I understood properly    
>>> text3
'<wpg3>10|300|defaultTemplate|</wpg3>'
>>> text4
'<wpg3>10|300||</wpg3>'

# Now with more than one tag
>>> text5
'<wpg3>10|300|defaultTemplate|eyJhbGlnbiI6ImFsaWdubGVmdCJ9</wpg3><wpg3>25|35|hello|world</wpg3>'
>>> text6
'<wpg3>10|300|defaultTemplate|eyJhbGlnbiI6ImFsaWdubGVmdCJ9</wpg3><wpg2>25|35|hello|world</wpg2>'

# This should fail because tags mismatch
>>> text7
'<wpg3>10|300|defaultTemplate|eyJhbGlnbiI6ImFsaWdubGVmdCJ9</wpg2>'

这里是测试:

# Parses as expected
>>> regex.match(text).groups()
('wpg3', None, '10', '300', 'defaultTemplate', 'eyJhbGlnbiI6ImFsaWdubGVmdCJ9', None)
>>> regex.match(text2).groups()
('wpg3', None, '10', '300', 'defaultTemplate', None, None)

# These two fail as expected
>>> regex.match(text3)
>>> regex.match(text4)

# Multi-tags now
>>> for m in regex.finditer(text5):
...    m.groups()
... 
('wpg3', None, '10', '300', 'defaultTemplate', 'eyJhbGlnbiI6ImFsaWdubGVmdCJ9', None)
('wpg3', None, '25', '35', 'hello', 'world', None)
>>> for m in regex.finditer(text6):
...    m.groups()
... 
('wpg3', None, '10', '300', 'defaultTemplate', 'eyJhbGlnbiI6ImFsaWdubGVmdCJ9', None)
('wpg2', None, '25', '35', 'hello', 'world', None)

# The last one fails (tag mismatch)
>>> regex.match(text7)

这符合您的需要吗?

【讨论】:

  • 如何从你的模式中创建一个 preg_replace 字符串?看起来你得到了我需要的东西,但我得到了一个“未知的修改器”(“错误:?也许一件事:我需要匹配“”-标签在上/下-至少是这样。我不在乎我是否也会匹配 wpg3id。
  • 终于:$return = preg_replace_callback('/([^>]*)?/i' , 数组($this, 'wpg3_content'), $content);根据您的第一个建议,explode("|", $g3_tag[0]) 做到了:D 谢谢!
  • @digitaldonkey:很高兴它有效。如果回答您的问题,请将答案标记为已接受:-)
猜你喜欢
  • 1970-01-01
  • 2011-10-19
  • 2011-01-26
  • 2015-01-13
  • 2012-08-13
  • 2013-05-21
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
相关资源
最近更新 更多