#regex #python-3.x
#регулярное выражение #python-3.x
Вопрос:
Я создал следующее регулярное выражение в Python 3, чтобы найти все слова в нижнем регистре в тексте и сослаться на первую букву и конец этого слова. Пример:
w ord
^ ^^^
| |
1st letter tail
После этого я использую цикл for, чтобы заменить все вхождения совпадений на первую группу, преобразованную в верхний регистр, и неизмененный хвост на строчную первую букву, за которой следует неизмененный хвост.
str = "Some text here and some more after that. Something that should remain untouched."
for match in re.finditer(r"b([a-z])([a-z] )b", str):
# print(match.group(1).upper() match.group(2)) # just for debugging
str = re.sub(r"b" match.group(1).upper() match.group(2) r"b", match.group(1) match.group(2), str)
print(str) #print the desired result
Есть ли способ сделать это в Python 3 с помощью одного регулярного выражения и без дополнительного процедурного кода? Кажется, что должен быть более элегантный способ, но я его не вижу (пока).
Для полноты картины: если код применяется к строке, хранящейся в str, это результат: немного текста здесь и еще немного после этого. Что-то, что должно остаться нетронутым.
Пожалуйста, обратите внимание, что RegEx-Replace может соответствовать только целым словам, но не частичным словам. 5-е слово в моем тексте — «some», это приводит к преобразованию 1-й буквы 1-го слова («Some») в в нижний регистр, но оставляет слово «Что-то», с которого начинается 2-е предложение, нетронутым.
Комментарии:
1. Можете ли вы просто описать, что вы пытаетесь получить вместо как вы пытаетесь это сделать? Простого до и после должно быть достаточно.
2. Ну, я хочу преобразовать все слова, начинающиеся с заглавной буквы, в одно и то же слово в нижнем регистре, ЕСЛИ слово встречается хотя бы один раз в нижнем регистре в тексте. Опубликованный мной код делает это правильно, но я пытаюсь избавиться от for и просто выполнить задачу только с регулярным выражением.
Ответ №1:
Вы не можете этого сделать с помощью re module
, поскольку он не поддерживает поиск переменной длины сзади, и поскольку при использовании встроенного модификатора, подобного (?i)
, он устанавливается для всего шаблона, и вы не можете его отключить. Это можно сделать с новым regex module
с помощью этого шаблона:
b([A-Z][a-z]*)b(?:(?=.*b(?=[a-z] b)(?i)1b)|(?<=b(?=[a-z] b)(?i)1b. ))
Однако я не уверен, что это более «элегантный» способ.
Можно протестировать шаблон с<a rel="noreferrer noopener nofollow" href="https:///regexstorm.net/tester?p=b([A-Z][a-z]*)b(?:(?=.*b(?=[a-z]+b)(?i)1b)|(?regexstorm.net/tester (поскольку движок регулярных выражений .net также допускает поисковые запросы переменной длины.)
Обратите внимание, что область действия встроенного модификатора ограничена подшаблоном после него и заканчивается первой закрывающей скобкой.
Комментарии:
1. Потрясающе, это именно то, что я искал. Оно стало немного больше, чем я ожидал, после того, как я потратил время на его просмотр, я думаю, что это довольно просто. Также БОЛЬШОЕ спасибо за ссылку regexstorm. Я раньше не знал эту страницу, здорово провести несколько быстрых тестов с регулярными выражениями и быстро получить визуальную обратную связь.