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