Регулярное выражение: 1) уменьшить все последовательные *
s, 2) re.escape
части между ?
и *
и 3) заменить каждый *
на .*
и ?
на.
при компиляции регулярного выражения с модификатором re.DOTALL
:
import re
def repl(m):
res = "{}{}".format(re.escape(m.group(1)), m.group(2).replace("*", ".*").replace("?", "."))
if m.group(3):
res += re.escape(m.group(3))
return res
def glob_to_regex(glob):
glob = re.sub(r'\*{2,}', '*', glob)
return '(?s)' + re.sub(r'([^?*]*)([*?]+)([^?*]+$)?', repl , glob)
l = ['baab', 'abbb', 'fc', 'AA', 'abb.']
print([x for x in l if re.search(glob_to_regex('?b*b'), x)])
print([x for x in l if re.search(glob_to_regex('?b*.'), x)])
См. Демонстрационную версию Python .
Здесь шаблон типа ?b***
будетпереводится в шаблон (?s).b.*
, что означает:
(?s)
- встроенный модификатор re.DOTALL
, который также делает .
разрывы строки соответствия .
- любой1 символ b
- b
символ .*
- любые 0+ символов как можно больше.
Если вынеобходимо поддерживать любой шаблон glob вам нужен метод fnmatch.filter(names, pattern)
, который принимает шаблон glob (это то, что ваши ?
и *
здесь, подстановочные знаки).
Уникальная проблема здесь в том, что fnmatch
глобусы должны совпадать со всем вводом, в то время как ваши шаблоны не зафиксированы.
Таким образом, вам нужно обернуть ваши шаблоны с помощью *
s:
import fnmatch
l = ['baab', 'abbb', 'fc', 'AA']
print(fnmatch.filter(l, '*{}*'.format('?b')))
print(fnmatch.filter(l, '*{}*'.format('?a')))
print(fnmatch.filter(l, '*{}*'.format('c?')))
print(fnmatch.filter(l, '*{}*'.format('b??b')))
print(fnmatch.filter(l, '*{}*'.format('???')))
print(fnmatch.filter(l, '*{}*'.format('b*b')))
print(fnmatch.filter(l, '*{}*'.format('***')))
Output:
['baab', 'abbb']
['baab']
[]
['baab']
['baab', 'abbb']
['baab', 'abbb']
['baab', 'abbb', 'fc', 'AA']
См. демонстрационную версию Python .