Получение отрезка символов в строке через регулярные выражения

Есть строки, к примеру:

a_god_by_berserk_0bllz.jpg
dream by FutureMan on ArtStation.png
a little old bymer.jpg
deathmatch by trixter.jpg
_ariel_santama__by_recphoto_fullview.jpg (1200×1860).jpg
4_new_photo_by_easypro.png

Нужно из всей этой мешанины вытащить всё то что содержит by(пробел либо земля) строка идущая до нижнего подчёркивания,точки или пробела. Как итог, из приведённого примера нужно вытащить: by_berserk, by FutureMan, by trixter, by_recphoto, by_easypro. Пробовал следующей регуляркой:

by( |_) *(\S|^_|^\.)*

Однако в любом случае, у меня выделяет диапазон либо от by до пробела, либо до конца строки, игнорируя последующие _ и . Последующие мофидирования регулярки вроде:

by( |_) *(?:\S|^_|^\.)*
by( |_) *(\S*|^_*|^\.)

ни к чему не приводят, всё остаётся так же. Так же интересно почему в начале регулярки в месте by( |) *, без пробела до * выделяет только не только by но и слова которые начинаются с by. С пробелом поиск c by и by_. Как пробел решает поведение шаблона - мне не понятно. Ведь по сути я даю шаблон: Ищи с сочетания символов by, затем должно следовать либо пробел, либо подчёркивание, а затем любое количество символов. Помогите с реализацией. Начал изучение регулярок и что-то как то уже не охото.


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

Автор решения: GrAnd
import re

strings = """
a_god_by_berserk_0bllz.jpg
dream by FutureMan on ArtStation.png
a little old bymer.jpg
deathmatch by trixter.jpg
_ariel_santama__by_recphoto_fullview.jpg (1200×1860).jpg
4_new_photo_by_easypro.png
"""

result = re.findall(r"(?:(?<=_)|\b)by[_\s].+?(?=\b|_)", strings)
print(result)

Результат:

['by_berserk', 'by FutureMan', 'by trixter', 'by_recphoto', 'by_easypro']

Расшифровка:

  • (?:(?<=_)|\b) - Проверка, что слева либо символ подчёркивания, либо граница слова. Причём подчёркивание проверяется методом "просмотра назад" (?<=...) - таким образом он не попадёт в результат. И используются группировки без создания группы (?:...), т.к. они нужны только в выражении, но в результате нам не интересны.
  • [_\s] - Символ подчёркивания или пробельный символ.
  • .+? - Любой символ в количестве больше нуля, но по-минимуму.
  • (?=\b|_) - Граница слова или символ подчёркивания. Опять же методом "просмотра вперёд" (?=...), чтобы в результат не попало.

Если сразу нужны только имена (без слова by), то достаточно будет поставить круглые скобки вокруг .+?, т.е. написать так: (.+?)

→ Ссылка