Шаблон регулярного выражения, который не соответствует определенным расширениям?

у меня такая схема написана

^.*\.(?!jpg$|png$).+$

Однако есть проблема - этот шаблон соответствует файлу.name.jpg (2 точки)

Работает корректно (не совпадает) на filename.jpg. Я пытаюсь понять, как сделать так, чтобы он не соответствовал ЛЮБЫМ файлам .jpg, даже если в имени файла есть 2 или более точек. Я попытался использовать просмотр назад, но python жалуется на то, что не использует фиксированную ширину (что я не совсем уверен, что это значит, но имя файла будет переменной длины).


person Shane Thornton    schedule 07.04.2012    source источник


Ответы (5)


Это должно работать: ^.*\.(?!jpg$|png$)[^.]+$

person bereal    schedule 07.04.2012

Если вам нужно только, чтобы строка не заканчивалась на .jpg или .png, вы можете использовать это:

^.+$(?<!\.jpg)(?<!\.png)

^.+ не является строго обязательным, но в зависимости от того, как закодирован синтаксический анализатор JSON, вам может потребоваться заставить регулярное выражение использовать всю строку. Если вы используете регулярное выражение и для других проверок, вам может понадобиться что-то более сложное, например:

^\w+(?:\.\w+)+$(?<!\.jpg)(?<!\.png)

Вы, вероятно, пытались использовать (?<!\.jpg|\.png), что не сработало бы, потому что разновидность регулярных выражений Python является одной из самых строгих, когда дело доходит до просмотра назад. PHP и Ruby 1.9+ приняли бы его, потому что каждый из вариантов имеет фиксированную длину. Они даже не должны быть одинаковой длины; (?<!\.jpg|\.jpeg|\.png) тоже подойдет. Только не пытайтесь исключить точку, как в (?<!\.(?:jpg|jpeg|png)); чередование должно быть на верхнем уровне ретроспективного просмотра.

Java примет версию с учетом фактора, потому что она выполняет немного больше работы во время компиляции, чтобы определить максимальное количество символов, которое может потребоваться для просмотра назад. Однако выражение просмотра назад должно быть довольно простым, и оно не может использовать квантификаторы + или *. Наконец, варианты .NET и JGSoft не накладывают никаких ограничений на просмотр назад. Но Python делает очень простодушную попытку вычислить точное количество символов, которое должно соответствовать ретроспективному анализатору, генерируя загадочное сообщение об ошибке в случае сбоя.

person Alan Moore    schedule 07.04.2012

Используйте изящные функции os.path, чтобы правильно разделить путь к файлу на компоненты для упрощения анализа:

filepath, filename = os.path.split(str)
basename, extension = os.path.splitext(filename)

if exension[1:] in ['jpg', 'png']:
  # The extension matches

Попробуйте это регулярное выражение (не делайте этого. Оно делает прямо противоположное тому, что вы хотите сделать):

\.(jpg|png)([^\.]|$)
person Blender    schedule 07.04.2012
comment
У меня нет доступа к Python, это механизм регулярных выражений Python, но у меня есть доступ только к файлу конфигурации JSON, чтобы поместить туда регулярное выражение для программы Python. Я удалил тег Python, чтобы избежать путаницы. - person Shane Thornton; 07.04.2012
comment
Ваше регулярное выражение выглядит так, будто оно пытается исключить строки, содержащие .jpg. или .png., но я считаю, что идея состоит в том, чтобы исключить все, что оканчивается на .jpg или .png. Регулярное выражение OP не работает, потому что и просмотр вперед, и окончательный .+$ могут совпадать после первого . в file.name.jpg. Изменение этого значения на [^.]+$, как это сделал @bereal, заставляет опережающий просмотр применяться только к последней последовательности с точками. - person Alan Moore; 07.04.2012

Похоже, у вас почти получилось:

.*\.(?!jpg$|png$)[^.]+

Согласно моим тестам (в java) я получаю следующие результаты:

file.jpg - false
file.png - false
file.name.jpg - false
file.name.png - false
file.gif - true
file.name.gif - true
file.jpg.gif - true
file.jpge - true

Если это не то, что вы хотели, пожалуйста, обновите свой вопрос своими ожиданиями.

person barsju    schedule 07.04.2012

Пожалуйста, попробуй

    .*\.(jpg$|png$)

Он будет правильно соответствовать имени файла.jpg. ваша попытка выяснить, как сопоставить ЛЮБЫЕ файлы .jpg, даже если в имени файла есть 2 или более точек, будет работать нормально.
При использовании скрипта Python убедитесь, что вы используете правильный тип разделения. другой тип разделения, а именно rsplit (правое разделение) и lsplit (левое разделение).

person Irengbam Tilokchan Singh    schedule 07.04.2012
comment
У вас все наоборот: регулярное выражение НЕ должно соответствовать filename.jpg ИЛИ file.name.png. Полагаю, filename.txt или file.name.foo в порядке. - person Alan Moore; 07.04.2012