2013-09-27 4 views
4

Я хочу исключить файлы «.txt» каталога с регулярным выражением (и только регулярным выражением). Но этот код не работает, и я не понимаю, почему. У меня есть этот список:Исключить файлы «.txt»

['/var/tmp/COMMUN/4.1.0_41/Apache', 
'/var/tmp/COMMUN/4.1.0_41/META-INF', 
'/var/tmp/COMMUN/4.1.0_41/RewriteRules', 
'/var/tmp/COMMUN/4.1.0_41/Robots', 
'/var/tmp/COMMUN/4.1.0_41/smokeTest', 
'/var/tmp/COMMUN/4.1.0_41/tutu.txt'] 

И я пытаюсь этот код

# list_dit is a personal function 
list_dir(toto, filter_function=lambda x: re.match("^.*(?!txt)$", x)) 

Любой посмотреть, что это не так?

+2

'' 'в начале вашего регулярного выражения является излишним, поскольку вы используете re.match, который соответствует только началу строки. Если бы вы использовали re.search, это было бы важно. – wich

+0

Обратите внимание, что вы хотите совместить полное расширение '.txt' вместо файлов, не заканчивающихся' txt': вы хотите, чтобы 'my_txt' соответствовал. – EOL

+0

Кроме того, я вижу, что вы не приняли никаких ответов на любые ваши вопросы, если вы хотите продолжать получать ответы на свои вопросы, вы должны принять некоторые ответы. – wich

ответ

4

Обычно .* жадные матчи, они будут соответствовать столько, сколько они могут со следующими еще соответствия. Поскольку пустая строка подходит для (?!txt), .* будет просто соответствовать всей строке, что означает, что это регулярное выражение будет соответствовать каждой строке.

Просто подходящий для .*\.txt$ и отрицающий re.match будет работать.

Кстати, вы должны использовать скомпилированное регулярное выражение вместо re.match, теперь регулярное выражение может быть скомпилировано для каждого файла в вашем каталоге. Если вы используете скомпилированное регулярное выражение, оно будет скомпилировано только один раз. Скомпилированное регулярное выражение может быть кэшировано модулем re, который в этом случае, вероятно, будет иметь место, поскольку между вызовами re.match нет других вызовов регулярных выражений. Однако, по моему мнению, это будет более «правильным», если вы сами скомпилируете регулярное выражение, таким образом, вы уверены, что он компилируется только один раз. Благодаря EOL для головок в кешировании.

+0

Вот и все! Спасибо за ваше объяснение. – elhostis

+0

@wich: Ваш комментарий о предварительной компиляции должен быть квалифицирован: более свежие шаблоны * не * перекомпилирован (http://docs.python.org/2/library/re.html#module-contents). Поэтому, если не требуется дополнительное ускорение, нет необходимости сначала компилировать регулярное выражение, так как это уже частично оптимизирован модулем 're'. – EOL

+0

Другое дело, что' not re.search ('\. txt', ...) $ 'является более простым решением. – EOL

2

Как насчет более простого решения?

x.endswith(".txt") 

Если необходимо использовать regeex:

not re.search("\\.txt$", x) 
  • notне матч
  • \\. одна точка .
  • txt
  • $ конец ввода
+2

Что такое '!' В python? – alecxe

+0

То же, что и на многих других языках: логическое отрицание –

+0

Да, это работает. Но мне не нужно решение. Мне нужно понять, почему это не работает для моего ума :) – elhostis

1

Anyone посмотреть, что это не так?

^ соответствует началу строки, затем .* матчи каждый символ во входной строке, теперь приходит (?!txt) и нет ничего, во входной строке в этой точке, но строка с истекшим так она проходит каждый раз, после этого $ соответствует концу строки.

Вы можете исправить это с гораздо более простым регулярным выражением, как это:

list_dir(toto, filter_function=lambda x: not re.search(r"\.txt$", x)) 
+0

Вероятно, вы имеете в виду 're.search', а не' re.find' – wich

+0

@wich Спасибо, я не работаю с Python, я исправлю это прямо сейчас. –

4

Причина ^.*(?!txt)$ не работает, потому что вы используете отрицательный предпросмотр, но, как из-за алчной природы .* и якоря $ вы в конце строки, и, таким образом, есть ничего впереди в этот момент, (так что для этого нет ничего неудачного).

Что вы пытаетесь сделать, может быть достигнуто с помощью отрицательного просмотра назад, который работает в обратном направлении, и выглядит как (^.*(?<!txt)$)

Следует отметить, что в то время как здесь работает с просмотром назад, Python позволяет только строки фиксированной длины для него (lookahead не имеет этого ограничения).
Другие реализации регулярных выражений позволяют ограниченные длины lookbehinds (то есть не могут использовать .*, но могут делать .{0,10}), в то время как другие (включая JavaScript) не поддерживают lookbehind вообще.

(Если вам нужно это для нефиксированного матча или в среде JS, предложение Wich о .*txt$ то отрицая результат может решить, что.)

Для получения дополнительной информации о как опережающем просмотре и просмотре назад, посмотри на этой странице: http://www.regular-expressions.info/lookaround.html

(конечно, вы должны быть в идеале с помощью \.txt в регулярном выражении, чтобы обеспечить его полное расширение, и наиболее эффективное решение, скорее всего, уже предложил x.endswith('.txt') метод.)

Смежные вопросы