Python Regex:如何将文件名与可选后缀匹配?为什么'(。*?)(\。后缀)?'不起作用?

时间:2013-11-29 09:10:39

标签: python regex

我有这样的文件名:

xxx 
xxx.suffix 
xxx 
xxx.suffix

我想找到所有的xxx(可能是任何东西,但不包含'.suffix')并删除后缀。

我试过(。*?)(。后缀)?我希望第一组能够非贪婪地匹配任何东西,而第二组则是可选的。

但这不起作用。我得到的是:

('', None)

我正在使用Python,代码是:

patt = re.compile(r'(.*?)(\.suffix)?')
print patt.match(str).groups()

编辑:显然以('。suffix')结尾也有效,但我不知道。

4 个答案:

答案 0 :(得分:4)

空字符串是正则表达式的有效匹配,因此它与所有输入的匹配。

在正则表达式的末尾添加“$”(字符串结尾)表示您在匹配后不希望字符串中有更多数据。

>>> re.compile( r'(.*?)(\.suffix)?$' ).match("xxx.suffix" ).groups()
('xxx', '.suffix')

答案 1 :(得分:3)

当你使第一部分非贪婪时,它甚至在开始时匹配空字符串。由于第二部分是可选的,因此省略,因此None

另一种解决方案:

a = 'xxx xxx.suffix xxx xxx.suffix'
l = a.split()
patt = re.compile(r'(.*?)(\.suffix)?$')
print [patt.match(i).groups() for i in l]

打印

[('xxx', None), ('xxx', '.suffix'), ('xxx', None), ('xxx', '.suffix')]

为什么呢?因为现在,正则表达式使用$锚定到字符串的末尾。

  • 根据您计划对结果执行的操作,使用

    可能也很有用
    patt = re.compile(r'(.*?)(\.suffix|)$')
    

    它会为您''而不是None。这样可以简化琴弦的重新组装。

  • 当然,问题是你真的需要正则表达式。

    print [p[:2] for p in (i.partition('.suffix') for i in l)]
    

    产生相同的结果

    [('xxx', ''), ('xxx', '.suffix'), ('xxx', ''), ('xxx', '.suffix')]
    

    并且速度更快:

    >>> import timeit
    >>> timeit.timeit(lambda: [p[:2] for p in (i.partition('.suffix') for i in l)])
    2.1371913756093956
    >>> timeit.timeit(lambda: [patt.match(i).groups() for i in l])
    5.259215670919147
    

    结果是1000000次呼叫所需的时间(以秒为单位)。

答案 2 :(得分:1)

为什么不使用endswith

>>> a = 'xxx xxx.suffix xxx xxx.suffix'
>>> a = a.split()
>>> a
['xxx', 'xxx.suffix', 'xxx', 'xxx.suffix']
>>> [s for s in a if s.endswith('.suffix')]
['xxx.suffix', 'xxx.suffix']

答案 3 :(得分:0)

我找到了一个解决方案,你不必先拆分。有关解释和正则表达式测试,调试等,请查看此处:http://regex101.com/r/aL7dQ2

a = """
xxx 
xxx.suffix 
xxx 
xxx.suffix
"""
patt = re.compile(r'(\S+?\b)(\.suffix)?')
patt.findall(a)

<强>输出:

[('xxx', ''), ('xxx', '.suffix'), ('xxx', ''), ('xxx', '.suffix')]