我想用正则表达式(只有正则表达式)排除目录的“.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))
任何人都看错了什么?
答案 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))