Задать вопрос
@Akshin17
Пайтон програмист

Как написать регулярное выражение?

<a>
<b>test</b>
<b>test</b>
</a>

<a>
<b>test</b>
<b>test</b>
</a>

<c>
<b>test</b>
<b>test</b>
</c>
По идее простая задача :

Нужно вывести все test которые находятся по пути a>b
пишу что то подобное :
[\s\S]*?([\s\S]*?)<\/b>[\s\S]*?<\/a> но это выраж...
  • Вопрос задан
  • 90 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ответы на вопрос 2
trapwalker
@trapwalker
Программист, энтузиаст
Очень плохая идея парсить html регулярными выражениями. Они не для этого предназначались. Есть специальные инструменты для этой цели, которые извлекают данные по xpath.
Ответ написан
Комментировать
erge
@erge
Примус починяю
какой ЯП?
можно находить блоки <a>...</a>
а уже внутри них искать блоки <b>...</b>

одной регуляркой, это......... м...

одной регуляркой даже скорее невозможно, только если знать точное количество блоков <b>...</b>
или точнее... хотя бы максимальное их количество...

например максимум их может быть 4, тогда можно написать регулярку вида:
(?<=<a>)(\s*?<b>([^<]+)<\/b>)(\s*?<b>([^<]+)<\/b>)?(\s*?<b>([^<]+)<\/b>)?(\s*?<b>([^<]+)<\/b>)?


матчим и в каждом "матче" (совпадении) - если существует группа с нечетным номером, то в следующей группе с четным номером будет собственно значение, т.е. нам нужны только четные группы.

см, regex101

PS:
можно было бы и так... (?<=<a>)(\s*?<b>([^<]+)<\/b>){1,}
матчиться оно будет, НО, вот группа будет только одна и писаться в нее будет последнее найденное значение.

как-то так....

UPDATE
взяв сгенерированный код в python с regex101, допиливаем "решение в лоб"

regex = r"(?<=<a>)(\s*?<b>([^<]+)<\/b>)(\s*?<b>([^<]+)<\/b>)?(\s*?<b>([^<]+)<\/b>)?(\s*?<b>([^<]+)<\/b>)?"

test_str = '''
<a>
<b>test11</b>
</a>

<a>
<b>test21</b>
<b>test22</b>
</a>

<a>
<b>test31</b>
<b>test32</b>
<b>test33</b>
</a>

<a>
<b>test41</b>
<b>test42</b>
<b>test43</b>
<b>test44</b>
</a>

<c>
<b>test51</b>
<b>test52</b>
</c>
'''

matches = re.finditer(regex, test_str, re.MULTILINE)

for matchNum, match in enumerate(matches, start=1):
    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1
        if (groupNum % 2 == 0) & (match.group(groupNum) != None):
            print (match.group(groupNum) )


см. пример
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы