Python находит несколько совпадений с регулярным выражением в совпадении с регулярным выражением - PullRequest
0 голосов
/ 05 ноября 2018

Я пытаюсь использовать re.sub (), чтобы изменить все HTML-теги < и > на { и }. Вот подвох: я хочу изменить только совпадения между <table и </table>.

Я не могу на всю жизнь найти учебник по регулярному выражению или пост, в котором можно изменять каждое совпадение регулярного выражения, но только между двумя другими совпадениями регулярного выражения. Я смотрел на положительные / отрицательные уроки по заглядыванию вперед и назад, но не повезло. Прошло добрых несколько часов поиска, прежде чем отправлять сообщения.

Вот лучшее, что у меня есть:

(?<=<table)(?:.*?)(<)(?:.*)(?=<\/table>)

Это будет соответствовать одному «<» между тегами начала и конца таблицы, но я не знаю, как сделать так, чтобы оно совпадало с несколькими. Я играл с ленивыми или не ленивыми группами с любым персонажем и т. Д., Но не повезло. </p>

Смысл всего этого в том, что у меня есть строка с большим количеством HTML, и я хочу сохранить все теги HTML внутри таблиц, а также сами таблицы.

Мой текущий план состоит в том, чтобы изменить все теги в таблицах (и сами теги таблицы) на {или}, затем удалить все теги HTML <и> во всем документе, а затем изменить все {и} обратно на < и>. Это должно сохранить таблицы (и любые другие теги внутри).

Пример ввода:

<font style = "font-family:inherit>
<any other HTML tags>

random text

<table cellpadding="0" cellspacing="0" style="font-family:times new 
roman;font-size:10pt;width:100%;border-collapse:collapse;text-align:left;">
<tr>
<td colspan="3">
<font style="font-family:inherit;font-size:12pt;font- 
weight:bold;">washington, d.c. 20549</font>
random text
<any other HTML tags within table tags>
</td>
</table>

random text

<font style = "font-family:inherit>

Пример вывода:

<font style = "font-family:inherit>
<any other HTML tags>

random text

{table cellpadding="0" cellspacing="0" style="font-family:times new 
roman;font-size:10pt;width:100%;border-collapse:collapse;text-align:left;"}
{tr}
{td colspan="3"}
{font style="font-family:inherit;font-size:12pt;font- 
weight:bold;"}washington, d.c. 20549{/font}
random text
{any other HTML tags within table tags}
{/td}
{/table}

random text

<font style = "font-family:inherit>

Спасибо, Грог

Ответы [ 3 ]

0 голосов
/ 05 ноября 2018

Вы можете использовать следующее регулярное выражение для сопоставления, а затем заменить на Group 1:

[\s\S]*(<table[\s\S]*?</table>)[\s\S]*

Это будет соответствовать чему-либо до '<table', затем создать Group 1 с содержимым таблицы, а затем сопоставить все после этого.

Заменить на:

$1

Это даст вам только таблицу с содержанием.

0 голосов
/ 05 ноября 2018

Как упомянул Серж, на самом деле это не проблема, которую вы хотите решить с помощью одного регулярного выражения, но с несколькими регулярными выражениями и некоторой магией Python:

def replacer(match):  # re.sub can take a function as the repl argument which gives you more flexibility
    choices = {'<':'{', '>':'}'}  # replace < with { and > with }
    return choices[match.group(0)]

result = []  # store the results here
for text in re.split(r'(?s)(?=<table)(.*)(?<=table>)', your_text): # split your text into table parts and non table parts
    if text.startswith('<table'): # if this is a table part, do the <> replacement 
        result.append(re.sub(r'[<>]', replacer, text))
    else: # otherwise leave it the same
        result.append(text)
print(''.join(result)) # join the list of strings to get the final result

ознакомьтесь с документацией по использованию функции для аргумента repl для re.sub здесь

И объяснение регулярных выражений:

(?s)        # the . matches newlines 
(?=<table)  # positive look-ahead matching '<table'
(.*)        # matches everything between <table and table> (it is inclusive because of the look-ahead/behinds)   
(?<=table>) # positive look-behind matching 'table>'

Также обратите внимание, что, поскольку (.*) входит в группу захвата, он включается в вывод строк с помощью re.split (см. здесь )

0 голосов
/ 05 ноября 2018

Не будь слишком строг с собой. Я не уверен, что это возможно в один выстрел со стандартным повторным сабвуфером. На самом деле, я думаю, что это либо невозможно, либо очень сложно. Например, пользовательские функции в замене (вы можете добавить множество пользовательских функций в свою пользовательскую функцию, вплоть до целого парсера html)

Вместо этого я настоятельно рекомендую простое решение разбить и собрать с помощью split / join, или, возможно, вы остановитесь на последовательности повторных замен.

Предполагая, что одна таблица l = s.split('table>'); l = [1] даст вам содержимое таблицы и l.split (. Множественная версия ниже

def curlyfy_el(s, tag='table'):

    return ('{%s' % tag).join(
                        [ ('{/%s}' % tag).join(
                                   [y if i != 0 else y.replace("<",  "{").replace(">", "}")
                                 for i, y in enumerate(x.split( '</%s>' % tag, 1)) 
    for x in s.split('<%s' % tag) ])

Слайти более читабельный

def curlyfy_el(s, tag='table'):
    h, *t = s.split('<%s' % tag)  # stplit on some pretable text and fragments starting with table
    r = [h]
    for x in t:
        head, *tail = x.split('</%s>' % tag, 1)  # select table body and rest, 1 is to keep duplicate closure of tag in one str
        head = head.replace("<", "{")
        head = head.replace(">", "}")
        r.append( ('{/%s}' % tag).join([head, *tail]))
    return ('{/%s}' % tag).join(r)

Как правило, для обработки HTML лучше всего использовать некоторые специально предназначенные библиотеки синтаксического анализа, такие как Beautiful Soup, код ad -hoc не будет работать во многих угловых случаях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...