排除“.txt”文件

时间:2013-09-27 08:34:49

标签: python regex

我想用正则表达式(只有正则表达式)排除目录的“.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))

任何人都看错了什么?

4 个答案:

答案 0 :(得分:4)

通常.*是贪婪的匹配,它们会尽可能多地匹配以下匹配。由于空字符串是(?!txt)的正常匹配,.*将匹配整个字符串,这意味着此正则表达式将匹配每个字符串。

只需匹配.*\.txt$并取消re.match即可。

顺便说一句,您应该使用已编译的正则表达式而不是re.match,现在可以为目录中的每个文件编译正则表达式。如果使用编译的正则表达式,它只会被编译一次。编译的正则表达式可以由re模块缓存,在这种情况下可能是这种情况,因为re.match调用之间没有其他正则表达式调用。但是,在我看来,如果你自己编译正则表达式会更加“正确”,那么你确定它只编译一次。感谢EOL提供缓存。

答案 1 :(得分:4)

^.*(?!txt)$不起作用的原因是因为你使用的是负面预测,但是,由于.*的贪婪性和你所在的$锚字符串的结尾,因而此前没有任何内容,(因此没有任何内容可以使其失败)。

你想要做的事情可以通过负面的后视来实现,它会向后工作,看起来像(^.*(?<!txt)$)

应该注意的是,虽然lookbehind在这里工作,但Python只允许固定长度的字符串(前瞻没有这个约束)。
其他正则表达式实现允许有限长度的lookbehinds(即不能使用.*但可以.{0,10}),而其他(包括JavaScript),根本不支持lookbehind。

(如果您需要这个用于非固定匹配或在JS环境中,那么建议.*txt$然后否定结果可以解决这个问题。)

有关前瞻和后瞻的更多信息,请查看此页面:http://www.regular-expressions.info/lookaround.html

(当然,理想情况下,您应该在正则表达式中使用\.txt来确保它是完整的扩展,而最有效的解决方案可能是已建议的x.endswith('.txt')方法。)

答案 2 :(得分:2)

一个更简单的解决方案怎么样?

x.endswith(".txt")

如果必须使用regeex:

not re.search("\\.txt$", x)
  • not 匹配
  • \\.一个点.
  • txt
  • $输入结束

答案 3 :(得分:1)

  

任何人都看错了什么?

^匹配字符串的开头,然后.*匹配输入字符串中的每个字符,现在来(?!txt)并且此时输入字符串中没有任何内容但是在$匹配字符串结尾之后,每次都会传递字符串结尾。

您可以使用更简单的正则表达式来修复此问题:

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