Могу ли я использовать регулярные выражения для замены всех ключевых слов в строке? (Python) - PullRequest
0 голосов
/ 19 марта 2020

Вот мой код:


# case 1
content = "staging_datastorage"
query_term = "st ta ag"

# case 2
# content = "game_event"
# query_term = "gam ame"

terms = re.findall('[a-z0-9]+', query_term, re.I)
terms.sort(key=len, reverse=True)
term_regex = "|".join(terms)
replace_content = re.sub(rf"({term_regex})", r'<em>\1</em>', content, flags = re.I)
print(replace_content)

Я хочу использовать тег <em> HTML, чтобы выделить некоторые ключевые слова в таблице (называемые content) с моей входной строкой ( query_term). Входная строка содержит ключевое слово, которое я хочу выделить и разделить на пробел .

Для двух случаев я хочу получить следующие результаты:

case 1:
this is better
<em>stag</em>ing_da<em>tast</em>or<em>ag</em>e
this is also fine(nesting highlight tag): 
<em>s<em>t<em></em>a</em>g</em>ing_da<em>ta<em></em>st</em>or<em>ag</em>e

case 2:
perfect result: 
<em>game</em>_event
fine result: 
<em>g<em>am</em>e</em>_event

Мой код есть ошибка: для случая 2 он только выделяет gam, а не nam, этот результат неверен: <em>gam</em>e_event

Я думаю, что эта ситуация немного сложнее, когда одно ключевое слово является вложенным в другом одно или одно ключевое слово является начальной (или конечной) частью другого.

Могу ли я использовать регулярное выражение для решения этой проблемы?

1 Ответ

1 голос
/ 20 марта 2020

Как я уже сказал в комментариях, поиски не перекрываются, следующий найденный находится в оставшейся части.

Что вы можете сделать идея # 1 :

re.sub каждое ключевое слово отдельно в al oop.

Конечно, если поиски перекрываются, вы можете иметь некоторые <em> или </em>, которые уже находятся на пути - как здесь, ame не будет совпадать с am</em>e - поэтому вам нужно изменить регулярные выражения с одним ключевым словом. Включите (?:</?em>)? между буквами.

terms = re.findall('[a-z0-9]+', query_term, re.I)
terms.sort(key=len, reverse=True)
replace_content = content
for term in terms:
    term_regex = "(?:</?em>)?".join(term)
    replace_content = re.sub(rf"({term_regex})", r'<em>\1</em>', replace_content, flags = re.I)

print(replace_content)

Результаты для обоих случаев:

<em>s<em>t</em><em>a</em>g</em>ing_da<em>ta</em><em>st</em>or<em>ag</em>e
<em>g<em>am</em>e</em>_event

Идея # 2

Вы можете предварительно обработать сами ключевые слова, найти, какие префиксы соответствуют суффиксам, и объединить их с другими ключевыми словами.

Здесь: gam имеет суффикс am, ame имеет префикс am - > вы добавляете game к вашим условиям.

Эта идея даст этот "идеальный результат"


Идея № 3 *

Сделайте идею № 1, удалите вложенные блики и объедините те, которые находятся рядом друг с другом (ie удалить </em><em>).

Эта идея даст этот "идеальный результат" "также.

Чтобы удалить один уровень вложенности, выполните:

re.sub(r"<em>([^/]*)<em>([^/]*)</em>([^/]*)</em>", r"<em>\1\2\3</em>", replace_content, flags = re.I)

Регулярное выражение работает, находя теги в порядке <em> <em> </em> </em> (вложенный) с любыми группами символов без / между ними (быстрый способ убедиться, что мы берем только ближайший закрывающий тег).

Очевидно, только с одним уровнем вложенности Если удалить, нам нужно использовать это также в al oop - это будет while l oop: хотя замены отличаются от прошлых раз, замена снова = останавливается, когда замена больше не вносит изменений.

final_result = ""
while final_result != replace_content:
    final_result = replace_content
    replace_content = re.sub(r"<em>([^/]*)<em>([^/]*)</em>([^/]*)</em>", r"<em>\1\2\3</em>", final_result, flags = re.I)

print(final_result)

В случае Case2 требуется только одна замена, поэтому давайте посмотрим, как она работает с case1:

<em>stag</em>ing_da<em>ta</em><em>st</em>or<em>ag</em>e

Теперь для этого нужно только удалить </em><em>, как я уже говорил!

Окончательный фрагмент кода, который нужно поставить после кода идеи № 1:

final_result = ""
while final_result != replace_content:
    final_result = replace_content
    replace_content = re.sub(r"<em>([^/]*)<em>([^/]*)</em>([^/]*)</em>", r"<em>\1\2\3</em>", final_result, flags = re.I)

final_result = final_result.replace("</em><em>", "")
print(final_result)

Дает:

<em>stag</em>ing_da<em>tast</em>or<em>ag</em>e
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...