Регулярное выражение для поиска тега (preg_replace_callback) - PullRequest
1 голос
/ 11 февраля 2011

Мне нужно найти все вхождения тега для плагина WP.

<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 голосов
/ 11 февраля 2011

вы можете сделать preg_match_all для тегов в первую очередь

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

, а затем перебрать массив $ out, где вы должны иметь имя тега и его содержимое.

, если тег совпадаетто, что вы хотите

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

или вы хотите сделать все в своем регулярном выражении?

0 голосов
/ 11 февраля 2011

Как только вы ответите на мой комментарий выше, у меня может быть что-то более точное.Вот что у меня так далеко.Я сделал это на 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)

Это соответствует тому, что вам нужно?

...