我在python 2.7.7中使用os.walk搜索一个非常复杂的目录树,并希望通过对结果目录使用修剪来限制搜索
import os,re
dirExclude = set(['amip4K','amip4xCO2','aqua4K','aqua4xCO2'])
for (path,dirs,files) in os.walk(inpath,topdown=True):
dirs[:] = [d for d in dirs if d not in dirExclude]
# Do something
我想附加到这个dirExclude列表/设置与正则表达式r' decadal [0-9] {4}'匹配的任何内容,但是我很难确定如何最好地使用常规我的列表/集合定义中的表达式?
这里有什么建议吗?或者确实是一种使用os.walk函数的更有效方法?
经过多次建议后,上述内容可以改进为:
import os,re
dirExclude = set(['amip4K','amip4xCO2','aqua4K','aqua4xCO2'])
decExclude = re.compile(r'decadal[0-9]{4}')
for (path,dirs,files) in os.walk(inpath,topdown=True):
dirs[:] = [d for d in dirs if d not in dirExclude and not re.search(decExclude,d)]
# Do something
在调查dir[:] =
与dir =
分配后,需要[:]
以确保os.walk使用已修剪的目录列表,而不是完整的(预先修剪的)目录列表
答案 0 :(得分:1)
为什么不直接检查dirExclude
中的r'decadal[0-9]{4}'
是否匹配,而不是添加到d
?
我在考虑这样的事情:
import re
dirExclude = set(['amip4K','amip4xCO2','aqua4K','aqua4xCO2'])
exre = re.compile(r'decadal[0-9]{4}')
for (path,dirs,files) in os.walk(inpath,topdown=True):
dirs = [d for d in dirs if d not in dirExclude and not exre.search(d)]
# Do something
说明:
如果exre.search(d)
内的正则表达式不匹配, None
将返回d
。然后,not None
将评估为True
。否则,exre.search(d)
将返回MatchObject
,not exre.search(d)
将评估为False
。
编译正则表达式是可选的。如果没有编译,你会发出
exre = r'decadal[0-9]{4}'
和
dirs = [d for d in dirs if d not in dirExclude and not re.search(exre, d)]
当您需要多次应用正则表达式以便仅编译一次编译时,编译会非常有用。但是,大多数情况下您不会注意到差异,因为即使您不手动编译正则表达式,Python也会缓存最后使用的正则表达式。确切地说,最后一百个正则表达式,尽管我得到的唯一参考是Jan Goyvaerts和Steven Levithan的正则表达手册。
答案 1 :(得分:1)
扩充之前的建议,您可以使用ifilterfalse
(或Python 3.x中的filterfalse
)来有效地过滤正则表达式:
from itertools import ifilterfalse
import re
import os
exclude = {'foo', 'bar', 'baz'}
expr = re.compile(r'decadal\d{4}')
for (path, dirs, files) in os.walk(inpath):
dirs[:] = set(ifilterfalse(expr.match, dirs)) - exclude
进一步说明:
dir = [alist]
是不够的,因为这只会修改本地标签dir
所指的内容(即它不再是指dirs
os.walk
使用的列表。您必须修改dirs
列出os.walk
引用的实际列表。您可以通过执行切片赋值运算符来执行此操作(如上所述)。这或多或少等同于表达式:dirs.__setitem__(slice(None, None), [alist])
答案 2 :(得分:0)
如果您只是想避免与re匹配的所有目录,您可以这样做:
d_re = re.compile(r'decadal[0-9]{4}')
dirs = [d for d in dirs if d_re.match(d) is None]
您可以通过以下方式检索所有被忽略的文件:
dirExclude = dirExclude.union(d for d in dirs if d not in dirExclude)
或
[dirExclude.add(d) for d in dirs if d not in dirExclude]