4

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

4 回答 4

4

通常.*是贪心匹配,它们会尽可能多地匹配下面的仍然匹配。因为一个空字符串是一个可以匹配的匹配,(?!txt)它将.*简单地匹配整个字符串,这意味着这个正则表达式将匹配每个字符串。

简单地匹配.*\.txt$和否定 re.match 就可以了。

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

于 2013-09-27T08:43:12.697 回答
4

^.*(?!txt)$不起作用的原因是因为您使用的是负前瞻,但是,由于贪婪的性质.*和锚点$,您处于字符串的末尾,因此此时没有任何东西,(所以它没有什么可以失败的)。

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

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

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

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

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

于 2013-09-27T08:43:24.537 回答
3

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

x.endswith(".txt")

如果您必须使用正则表达式:

not re.search("\\.txt$", x)
  • not 匹配
  • \\.一个点.
  • txt
  • $输入结束
于 2013-09-27T08:38:23.343 回答
1

有人看看有什么问题吗?

^匹配字符串的开头,然后.*匹配输入字符串中的每个字符,现在来(?!txt)了,此时输入字符串中除了字符串结尾之外什么都没有,所以它每次都通过,之后$匹配结尾-细绳。

您可以使用更简单的正则表达式来解决此问题,如下所示:

list_dir(toto, filter_function=lambda x: not re.search(r"\.txt$", x))
于 2013-09-27T08:43:01.067 回答