【问题标题】:python regex gives empty stringpython 正则表达式给出空字符串
【发布时间】:2013-02-15 04:13:48
【问题描述】:

首先,我是正则表达式的新手。但到目前为止,我爱上了他们。我正在使用正则表达式从我从渲染引擎获得的图像文件名中提取信息。到目前为止,这个正则表达式运行良好......

_([a-z]{2,8})_?(\d{1,2})?(\.|_)(\d{3,10})\.([a-z]{2,6})$

如果我对文件名使用 split() 方法,例如...

image_file_name_ao.0001.exr

我回来了我可以使用的不错的小清单....

['image_file_name', 'gi', None, '.', '0001', 'exr', '']

我唯一担心的是它总是最后返回一个空字符串。无论我如何更改或操作正则表达式,它总是在列表末尾给我一个空字符串。我完全可以忽略它并继续前进,但我的问题是我的正则表达式做错了什么,或者我能做些什么让它不通过最后的空字符串?感谢您的宝贵时间。

【问题讨论】:

  • 请看我对您问题的回答。但是,您为什么要使用 re.split 而不是像 Katzwinkel 的回答那样捕获组? - 顺便说一句,你为什么不分组捕获(\d{1,2})? 和最后一个点之前的潜在取消标记?

标签: python regex return


【解决方案1】:

难怪。 split 方法在出现正则表达式时拆分您的字符串(加上返回组范围)。而且由于您的正则表达式仅匹配到达行尾的子字符串(由其末尾的$ 表示),因此在文件名的末尾没有什么可以拆分的,只有一个空后缀('')。

鉴于您已经在表达式中使用了组“(...)”,您也可以使用re.match(regex, string)。这将为您提供一个MatchObject 实例,您可以通过groups() 从中检索包含您的组的元组:

# additional group up front
reg='(\S*)_([a-z]{2,8})_?(\d{1,2})?(\.|_)(\d{3,10})\.([a-z]{2,6})$' 
print re.match(reg, filename).groups() # request tuple of group matches

编辑:我真的很抱歉,但我没有意识到您的模式与文件名字符串的第一个字符不匹配。我在我的回答中扩展了它。如果您想坚持使用 split() 的方法,您还可以更改原始模式,使文件名的最后一部分不匹配,从而拆分。

【讨论】:

  • 感谢您的快速回答。我已经尝试了 match() 方法,但我只收到了一个 NoneType。我已经通过编译正则表达式以及您上面解释的方式进行了尝试,但没有任何影响。我上面使用的测试字符串在 split() 方法中运行良好,但似乎从未与 match() 方法一起使用。
  • 您可能没有注意到我对答案所做的修改。它就像现在显示的那样工作。试试re.match('(\S*)_([a-z]{2,8})_?(\d{1,2})?(\.|_)(\d{3,10})\.([a-z]{2,6})$', 'image_file_name_ao.0001.exr').groups(),我保证会成功的。对于造成的混乱,我深表歉意!
  • 我完全错过了那个补充,我的错。现在它运行良好,非常感谢您的帮助。
  • 我的荣幸!太好了,我可以提供帮助。如果你真的很喜欢正则表达式,你可能会考虑学习 Perl。
  • @J. Katzwinkel @Matt Pearson [g for g in m.groups()] 是组的列表。如果您绝对希望将组显示在列表中,list(re.match(reg, filename).groups()) 更直接。否则,在元组中使用 re.match(reg, filename).groups() 这是组的本机表示。也许您想要专门的组列表?
【解决方案2】:

有趣的问题。

我稍微改变了正则表达式的模式:

import re

reg = re.compile('_([a-z]{2,8})'

                 '_?(\d\d?)?'

                 '([._])'
                 '(\d{3,10})'
                 '\.'
                 '(?=[a-z]{2,6}$)')

for ss in ('image_file_name_ao.0001.exr',
           'image_file_name_45_ao.0001.exr',
           'image_file_name_ao_78.0001.exr',
           'image_file_name_ao78.0001.exr'):
    print '%s\n%r\n' % ( ss, reg.split(ss) )

结果

image_file_name_ao.0001.exr
['image_file_name', 'ao', None, '.', '0001', 'exr']

image_file_name_45_ao.0001.exr
['image_file_name_45', 'ao', None, '.', '0001', 'exr']

image_file_name_ao_78.0001.exr
['image_file_name', 'ao', '78', '.', '0001', 'exr']

image_file_name_ao78.0001.exr
['image_file_name', 'ao', '78', '.', '0001', 'exr']

【讨论】:

  • 我在过去一个小时的大部分时间里都在了解re.split() 与组结合时到底在做什么,而我得到的只是更加绝望。现在你出现了,我突然明白了!感谢您以强调单个模式的方式重新排列表达式。以及关于集合内特殊字符的提醒。
  • @Katzwinkel 事实上,乍一看,我并不清楚 OP 的代码是如何给出结果的。所以我做了和你一样的事情,我研究了re.split在模式中定义了几个组时的功能。然后,我准确地回答了这个问题,这是一个 XY 问题的 Y 问题。 (meta.stackexchange.com/questions/66377/what-is-the-xy-problem) 你回答了 X 问题。所以我赞成你值得接受的答案。
  • 感谢您再次启发我,@eyquem。我从来不知道有这样的专用术语,但这对我来说很有意义。很多时候,我很难确定 OP 中的实际问题。另一方面,新用户一开始可能会感到压力,因为其他人的问题因为没有提供足够的个人努力证明而被否决。许多人可能觉得他们最好至少想出一些东西,片刻之后,十个人再次与Y打交道。做这个很有趣,我很高兴学到了很多东西。干杯!
【解决方案3】:

您可以使用filter()

鉴于你的例子,这会像,

def f(x):
    return x != '' 

filter
(
    f,
    re.split('_([a-z]{2,8})_?(\d{1,2})?(\.|_)(\d{3,10})\.([a-z]{2,6})$',
    'image_file_name_ao.0001.exr')
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 2013-05-26
    • 2012-05-28
    • 1970-01-01
    相关资源
    最近更新 更多