正则表达式查找标记(preg_replace_callback)

时间:2011-02-11 12:21:39

标签: php regex html-parsing

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

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

有标签的可能版本(,,, ...)但是开始和结束匹配。这些组是可选的:应该表示可以没有或者一个,或两个或三个“|”,它们将选项分开。

我的问题:如果我的搜索字符串中只有一个标记,一切都会按预期工作。 但是如果我在我的字符串中添加第二个标记,则回调只调用一次,而不是每个标记调用一次。在开始或结束时必须缺少某些东西。 如果缺少最后一个参数(功能),则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
)

2 个答案:

答案 0 :(得分:0)

一旦你回答了我上面的评论,我可能会有更精确的话。这是我到目前为止所拥有的。我用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)来确保结束标记与开始标记匹配。我使用[^\|]保护匹配的内容略高于[^\|>],以防止出现多标记问题。

我的测试字符串:

# 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)

这是否符合您的需求?

答案 1 :(得分:0)

首先可以在标签上进行preg_match_all

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

然后遍历$ out数组,在那里你应该有标签名称和内容。

如果标签符合您的要求

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

或者您是否希望在正则表达式中执行所有操作?