Как написать регулярное выражение, которое выделит все строки отвечающие заданым условиям?

Пишу регулярное выражение, которое позволяет выделить все строки отвечающие условиям:

  • Состоят только из букв

  • Одна и только одна из букв является заглавной

Пример строк которые могут быть выделены выражением:

"Мама",
"авТо",
"гриБ",
'Яблоко', 'яБлоко', 'ябЛоко', 'яблОко', 'яблоКо', 'яблокО'

Пример строк, которые не должны быть выделены выражением:

`агент007` - содержит цифры, 
"стриж" - только строчные буквы, 
"ГТО", - более одной заглавной буквы, 
`Три богатыря` - содержит пробел, допустимы только буквы

Вот что у меня получилось:

[а-я]*[А-Я][а-я]+?\S 

Но все равно выделят слово "Три" в "Три богатыря".

Прверяю все через regex101


Ответы (4 шт):

Автор решения: ipatev_nn

По поводу попытки решения самостоятельно, попробуем разобрать ваше выражение и понять что не так:

[а-я]*[А-Я][а-я]+?\S
  • не указа граница строки, т.е. начало - ^
  • Проблема квантификатора, в случае если последняя буква в слове будет заглавной гриБ, слово не будет захвачено, нужно поменять местами квантификаторы, но что бы это работало корректно добавить их в группу (?:...|...)
  • Смягчение квантификатора не нужно +?
  • \S - любой не пробельный символ, т.е. все кроме \r\n\t\f\v , вероятнее всего хотели указать любой пробельный символ \s - но под этот шаблон попадает как раз Три из Три богатыря, поэтому правильней использовать $ - означающий конец строки

По итогу, если исправить все замечания, то получится такой шаблон:

^(?:[а-я]+[А-Я][а-я]*|[а-я]*[А-Я][а-я]+)$

Пример: regex101

→ Ссылка
Автор решения: Павел О.

Про букву Ёё забыли и мне кажется, выражение выше можно его упростить:

^([а-яё]*[А-ЯЁ][а-яё]*)$

получается: в начале стоки любое кол-во строчных букв (от 0 до бесконечности), далее одна прописная буква, потом снова любое кол-во строчных букв

→ Ссылка
Автор решения: Александр Козловцев

Правильным выражением для паттерна в Python будет

^[а-яёa-z]*[А-ЯЁA-Z]{1}[а-яёa-z]*$

если разбирать паттерн, то логика такая - строка может начинаться со строчных символов (кириллица или латиница) в кол-ве от нуля [а-яёa-z]*, далее должны встречаться прописные символы в кол-ве не более одного [А-ЯЁA-Z]{1}, ну и после прописного символа должны быть только строчные в любом кол-ве от нуля [а-яёa-z]*

→ Ссылка
Автор решения: Евгений Фёдоров

для Python:

import re

  txt = "Три богатыря", "проверка"

  for x in txt:
    c = re.findall(r"(^[а-я]*[А-Я][а-я]*)$", x)
    print(c)
  1. перебираем циклом все значения txt
  2. c помощью метода findall ищем все схождения
  3. задаем параметры поиска с одной заглавной буквой
→ Ссылка