glob.glob 中的正则表达式用法?
Posted
技术标签:
【中文标题】glob.glob 中的正则表达式用法?【英文标题】:Regular expression usage in glob.glob? 【发布时间】:2012-10-13 11:25:52 【问题描述】:import glob
list = glob.glob(r'*abc*.txt') + glob.glob(r'*123*.txt') + glob.glob(r'*a1b*.txt')
for i in list:
print i
此代码用于列出当前文件夹中名称中包含'abc'
、'123'
或'a1b'
的文件。
如何使用glob
来执行此功能?
【问题讨论】:
我不认为你可以。 python的glob不支持
,我认为这几乎是唯一的方法。
【参考方案1】:
最简单的方法是自己过滤 glob 结果。以下是使用简单循环理解的方法:
import glob
res = [f for f in glob.glob("*.txt") if "abc" in f or "123" in f or "a1b" in f]
for f in res:
print f
您也可以使用正则表达式而不使用glob
:
import os
import re
res = [f for f in os.listdir(path) if re.search(r'(abc|123|a1b).*\.txt$', f)]
for f in res:
print f
(顺便说一句,将变量命名为list
是个坏主意,因为list
是Python 类型...)
【讨论】:
我认为您的意思是or
而不是 and
,不是吗?
@Emmanuel 我不确定... OP 写了关于“名称中包含 'abc'、'123' 和 'a1b' 的文件”。但是看着在他的代码中,我猜or
实际上是一个更好的选择。感谢您指出这一点。
@user1561868 已更改 :) 英语没问题,它也不是我的母语。
res = [f for f in glob.glob(".txt") if re.match(r'[abc|123|a1b].', f) 【参考方案2】:
我很惊讶这里没有答案使用过滤器。
import os
import re
def glob_re(pattern, strings):
return filter(re.compile(pattern).match, strings)
filenames = glob_re(r'.*(abc|123|a1b).*\.txt', os.listdir())
这接受任何返回字符串的迭代器,包括列表、元组、字典(如果所有键都是字符串)等。如果您想支持部分匹配,您可以将.match
更改为.search
。请注意,这显然会返回一个生成器,因此如果您想使用结果而不对其进行迭代,您可以自己将结果转换为列表,或者使用 list(...) 包装 return 语句。
【讨论】:
re: Evan 它只有在我将 list() 添加到 filter() 函数时才对我有用。 def glob_re(pattern, strings): return list(filter(re.compile(pattern).match, strings)) 希望对您有所帮助。 @argan python 中的各种操作的结果都是惰性求值的,filter 就是其中之一。延迟评估在您正在编写的实际程序中很有用是有技术原因的,但是当您在 repl 中进行交互式编程时,它是一个持续不断的烦恼来源。我完全理解将它包装在一个交互式运行一次编码的列表中,但是当你不在单行代码的领域时,最好利用惰性评估。 @argan 为了让你的程序工作,你只需要通过一些可以迭代的东西(比如你提到的 list(x) )来提供变量。例如:for path in glob_re(pattern, string): print(path)
【参考方案3】:
根据其他答案,这是一种现成的方法。这不是最关键的性能,但它的工作原理与描述的一样;
def reglob(path, exp, invert=False):
"""glob.glob() style searching which uses regex
:param exp: Regex expression for filename
:param invert: Invert match to non matching files
"""
m = re.compile(exp)
if invert is False:
res = [f for f in os.listdir(path) if m.search(f)]
else:
res = [f for f in os.listdir(path) if not m.search(f)]
res = map(lambda x: "%s/%s" % ( path, x, ), res)
return res
【讨论】:
应该使用match
来完全匹配名称。投反对票。
我更喜欢 lambda x: os.path.join(path,x)
@user_na:更好的是,这应该在res
list-comprehension 中完成,而不是第二次循环遍历所有匹配项。
@martineau 确实如此。 if/else 也可以直接在列表推导的 if 语句中完成。但是使用 os.path.join 而不是字符串格式可能是我要解决的第一件事。【参考方案4】:
for filename in glob.iglob(path_to_directory + "*.txt"):
if filename.find("abc") != -1 or filename.find("123") != -1 or filename.find("a1b") != -1:
print filename
【讨论】:
您能否为您的答案添加一些解释? 这个想法基本上是遍历目录中文件的名称列表并找到名称中包含任何文本字符串的文件 如果您想要文件名称中包含所有字符串,您只需将“或”更改为“和”以上是关于glob.glob 中的正则表达式用法?的主要内容,如果未能解决你的问题,请参考以下文章