Дегридификация регулярного выражения в python

1

Я пытаюсь написать регулярное выражение, которое преобразует полное имя файла пути в короткое имя файла для заданного типа файла, за вычетом расширения файла.

Например, я пытаюсь получить только имя файла .bar из строки, используя

re.search('/(.*?)\.bar$', '/def_params/param_1M56/param/foo.bar')

Согласно Python re docs, *? - это нелогичная версия *, поэтому я ожидал получить

'foo'

возвращен для match.group(1), но вместо этого я получил

'def_params/param_1M56/param/foo'

Что мне здесь не хватает о жадности?

Теги:
greedy
non-greedy

7 ответов

8
Лучший ответ

То, что вам не хватает, связано не столько с жадностью, сколько с механизмами регулярных выражений: они работают слева направо, поэтому / соответствует как можно раньше, а .*? затем вынуждается работать оттуда, В этом случае лучшее регулярное выражение вовсе не связано с жадностью (вам нужно вернуться к работе, но это может занять очень много времени, если есть много косых черт), но более явный шаблон:

'/([^/]*)\.bar$'
  • 0
    Лучший ответ на данный момент.
3

Я бы предложил изменить ваше регулярное выражение, чтобы оно не зависело от жадности.

Вы хотите только имя файла перед расширением .bar и все после окончательного /. Это должно сделать:

re.search(`/[^/]*\.bar$`, '/def_params/param_1M56/param/foo.bar')

Что это значит, он соответствует /, а затем не более или более символов (насколько это возможно) не /, а затем .bar.

  • 0
    +1, сначала с лучшим
  • 0
    . в вашем регулярном выражении совпадает с чем угодно, вместо . файла расширения. Убедитесь, что вы избегаете . с \.
Показать ещё 2 комментария
0

Мне нравится regex, но здесь нет необходимости.

path = '/def_params/param_1M56/param/foo.bar'
print  path.rsplit('/',1)[1].rsplit('.')[0]

path = '/def_params/param_1M56/param/fululu'
print  path.rsplit('/',1)[1].rsplit('.')[0]

path = '/def_params/param_1M56/param/one.before.two.dat'
print  path.rsplit('/',1)[1].rsplit('.',1)[0]

результат

foo
fululu
one.before.two
  • 0
    Я действительно понял это сразу после того, как отправил вопрос. Все еще хотел знать о природе жадности, хотя. Вы также можете просто использовать path.split('/')[-1].split('.')[0]
0

Другие люди ответили на вопрос о регулярном выражении, но в этом случае более эффективный способ, чем регулярное выражение:

file_name = path[path.rindex('/')+1 : path.rindex('.')]
0

Регулярные выражения начинаются справа. Поместите a * в начале и он должен работать.

0

Я не претендую на то, чтобы хорошо понять неживые операторы, но решением этой конкретной проблемы было бы использовать ([^/] *?)

-1

попробуйте этот вариант для размера:

match = re.search('. */(. *?). bar $', '/def_params/param_1M56/param/foo.bar')

  • 0
    Если вы уже используете '.*/ , Я не думаю, что вам действительно нужно .*? , .* тоже будет работать :) Не могли бы вы отредактировать свой вопрос, чтобы я снова мог вас проголосовать?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню