使用 re.match 过滤字符串列表时失败 [重复]

Posted

技术标签:

【中文标题】使用 re.match 过滤字符串列表时失败 [重复]【英文标题】:Failure when filtering string list with re.match [duplicate] 【发布时间】:2016-03-11 03:12:33 【问题描述】:

我想使用正则表达式过滤 python 中的字符串列表。在以下情况下,仅保留扩展名为“.npy”的文件。

不起作用的代码:

import re

files = [ '/a/b/c/la_seg_x005_y003.png',
          '/a/b/c/la_seg_x005_y003.npy',
          '/a/b/c/la_seg_x004_y003.png',
          '/a/b/c/la_seg_x004_y003.npy',
          '/a/b/c/la_seg_x003_y003.png',
          '/a/b/c/la_seg_x003_y003.npy', ]

regex = re.compile(r'_x\d+_y\d+\.npy')

selected_files = filter(regex.match, files)
print(selected_files)

同样的正则表达式在 Ruby 中也适用于我:

selected = files.select  |f| f =~ /_x\d+_y\d+\.npy/ 

Python 代码有什么问题?

【问题讨论】:

你想用.npy 扩展过滤files 中的元素吗? 【参考方案1】:

只需使用search- 因为匹配从字符串的开头到结尾(即整个)开始匹配,并在字符串中的任何位置搜索匹配项。

import re

files = [ '/a/b/c/la_seg_x005_y003.png',
          '/a/b/c/la_seg_x005_y003.npy',
          '/a/b/c/la_seg_x004_y003.png',
          '/a/b/c/la_seg_x004_y003.npy',
          '/a/b/c/la_seg_x003_y003.png',
          '/a/b/c/la_seg_x003_y003.npy', ]

regex = re.compile(r'_x\d+_y\d+\.npy')

selected_files = filter(regex.search, files)
print(selected_files)

输出-

['/a/b/c/la_seg_x005_y003.npy', '/a/b/c/la_seg_x004_y003.npy', '/a/b/c/la_seg_x003_y003.npy']

【讨论】:

【参考方案2】:

如果您match,则该模式必须覆盖整个输入。 要么扩展你的正则表达式:

regex = re.compile(r'.*_x\d+_y\d+\.npy')

哪个匹配:

['/a/b/c/la_seg_x005_y003.npy',
 '/a/b/c/la_seg_x004_y003.npy',
 '/a/b/c/la_seg_x003_y003.npy']

或者使用re.search,其中

扫描字符串寻找正则表达式模式产生匹配的第一个位置 [...]

【讨论】:

【参考方案3】:

re.match() 在字符串的开头查找匹配项。你可以改用re.search()

【讨论】:

【参考方案4】:
selected_files = filter(regex.match, files)

re.match('regex') 等于 re.search('^regex')text.startswith('regex') 但正则表达式版本。 它只检查字符串是否以正则表达式开头

所以,请改用re.search()

import re

files = [ '/a/b/c/la_seg_x005_y003.png',
          '/a/b/c/la_seg_x005_y003.npy',
          '/a/b/c/la_seg_x004_y003.png',
          '/a/b/c/la_seg_x004_y003.npy',
          '/a/b/c/la_seg_x003_y003.png',
          '/a/b/c/la_seg_x003_y003.npy', ]

regex = re.compile(r'_x\d+_y\d+\.npy')

selected_files = list(filter(regex.search, files))
# The list call is only required in Python 3, since filter was changed to return a generator
print(selected_files)

输出:

['/a/b/c/la_seg_x005_y003.npy',
 '/a/b/c/la_seg_x004_y003.npy',
 '/a/b/c/la_seg_x003_y003.npy']

如果您只想获取所有.npy 文件,str.endswith() 将是更好的选择:

files = [ '/a/b/c/la_seg_x005_y003.png',
          '/a/b/c/la_seg_x005_y003.npy',
          '/a/b/c/la_seg_x004_y003.png',
          '/a/b/c/la_seg_x004_y003.npy',
          '/a/b/c/la_seg_x003_y003.png',
          '/a/b/c/la_seg_x003_y003.npy', ]


selected_files = list(filter(lambda x: x.endswith('.npy'), files))

print(selected_files)

【讨论】:

我想知道为什么filter() 接受re.search() 方法,因为后者返回MatchObject 的实例而不是布尔值。在 16.8.3 中解释了here:如果项目匹配,search()-方法返回一个 MatchObject,filter() 将其解释为 True。否则search() 返回 None,它被解释为 False。 在 Python 3.x 中,filter()returns a generator,所以如果你想要的话,你需要将它包装在 list() 中。

以上是关于使用 re.match 过滤字符串列表时失败 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

re.match与re.search的区别

re模块

re库

用python中re.match匹配为啥一直是None?

python正则表达式re.match函数

re.match re.search re.findall区别