使用正则表达式输入创建列表

时间:2014-08-20 17:58:34

标签: python regex list os.walk

我在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使用已修剪的目录列表,而不是完整的(预先修剪的)目录列表

3 个答案:

答案 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)将返回MatchObjectnot 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]