#python #regex #greedy #non-greedy
#python #регулярное выражение #жадный #нежадный
Вопрос:
Я пытаюсь написать регулярное выражение, которое преобразует полный путь к имени файла в короткое имя файла для данного типа файла за вычетом расширения файла.
Например, я пытаюсь получить просто имя файла .bar из строки, используя
re.search('/(.*?).bar$', '/def_params/param_1M56/param/foo.bar')
Согласно документам Python re, *?
это ungreedy версия *
, поэтому я ожидал получить
'foo'
возвращено для match.group(1)
но вместо этого я получил
'def_params/param_1M56/param/foo'
Чего я здесь не понимаю о жадности?
Ответ №1:
Чего вам не хватает, так это не столько жадности, сколько движков регулярных выражений: они работают слева направо, поэтому /
совпадения выполняются как можно раньше, а .*?
затем вынуждены работать оттуда. В этом случае лучшее регулярное выражение вообще не связано с жадностью (для этого вам нужно выполнить возврат; это сработает, но может занять действительно много времени, если в нем много косых черт), но более явный шаблон:
'/([^/]*).bar$'
Ответ №2:
Я бы посоветовал изменить ваше регулярное выражение, чтобы оно не зависело от жадности.
Вам нужно только имя файла перед расширением .bar
и все после окончательного /
. Это должно сделать:
re.search(`/[^/]*.bar$`, '/def_params/param_1M56/param/foo.bar')
Что это делает, так это то, что оно соответствует /
, затем нулю или более символов (насколько это возможно), которые не /
являются, а затем .bar
.
Комментарии:
1.
.
в вашем регулярном выражении соответствует чему угодно, вместо.
файла расширения. Убедитесь, что вы экранируете.
с помощью.
2. Упс 🙂 Отредактировано. Я надеюсь, что это не было причиной для понижения голоса, поскольку это не имеет отношения к проблеме.
3. снова поддержано 😉 хотя это может быть неуместно для этой проблемы, возможно, OP захочет использовать его (сейчас или позже) для сопоставления файлов с расширением
bar
или чем-то еще, и это тоже будет соответствовать.abar
, например 🙂
Ответ №3:
Я не утверждаю, что так уж хорошо разбираюсь в нежадных операторах, но решением этой конкретной проблемы было бы использовать ([^ /] *?)
Ответ №4:
Регулярные выражения начинаются справа. Поместите .* в начале, и это должно сработать.
Ответ №5:
Мне нравится регулярное выражение, но здесь оно не нужно.
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
Комментарии:
1. На самом деле я понял это сразу после того, как опубликовал вопрос. Все еще хотел узнать о природе жадности, хотя. Вы также можете просто использовать
path.split('/')[-1].split('.')[0]
Ответ №6:
Другие люди отвечали на вопрос о регулярном выражении, но в этом случае есть более эффективный способ, чем регулярное выражение:
file_name = path[path.rindex('/') 1 : path.rindex('.')]
Ответ №7:
попробуйте это для размера:
совпадение = повторный поиск(‘.*/(.*?). bar$’, ‘/def_params/param_1M56/param/foo.bar’)
Комментарии:
1. Если вы уже используете
'.*/
, я не думаю, что вам действительно нужно.*?
..*
тоже будет работать 🙂 Не могли бы вы отредактировать свой вопрос, чтобы я мог снова поддержать вас?