-1

我有一堆这种风格的字符串:

#q1_a1
#q7

基本上 # 是必须忽略的符号。# 之后是一个单字母字母加上一些数字。可选地,可以在_(下划线)之后跟随一些字母+数字组合。

这是我想出的:

>>> pat = re.compile(r"#(.*)_?(.+)?")
>>> pat.match('#q1').groups()
('q1', None)

问题是#q1_a1格式字符串。当我将所做的应用于此类字符串时:

>>> pat.findall('#q1_f1')
[('q1_f1', '')]

有什么建议么?

4

4 回答 4

3

正如其他人所说,您的正则表达式越具体,匹配它不应该匹配的东西的可能性就越小:

In [13]: re.match(r'#([A-Za-z][0-9])(?:_([A-Za-z][0-9]))?', '#q1_a1').groups()
Out[13]: ('q1', 'a1')

In [14]: re.match(r'#([A-Za-z][0-9])(?:_([A-Za-z][0-9]))?', '#q1').groups()
Out[14]: ('q1', None)

笔记:

  1. 如果您只需要匹配整个字符串,请用^and包围正则表达式$
  2. 您说“某个数字”,但您的示例仅包含一个数字。如果您的正则表达式需要接受多个数字,请将 更改[0-9][0-9]+.
于 2013-01-27T07:47:33.383 回答
2

您的“。*”匹配也下划线,因为匹配是贪婪的。更好地创建更具体的正则表达式,以从第一组中排除下划线。

正确的正则表达式可能如下所示:

#([a-z][0-9])_?([a-z][0-9])?

但是您需要检查它是否适用于您期望的所有数据。

附言。在正则表达式中更具体会更好,因为您的误报更少。

于 2013-01-27T07:39:41.343 回答
1

当你使用.*时,它会贪婪匹配尽可能多的。尝试:

>>> pat = re.compile(r"#([^_]*)_?(.+)?")
>>> pat.findall('#q1_f1')
[('q1', 'f1')]

同样,最好写一个更具体的表达式:

#([a-z][0-9])(?:_([a-z][0-9]))?
于 2013-01-27T07:42:48.200 回答
0

不使用正则表达式的简单替代方案:

s = '#q7'
print s[1:].split('_')
# ['q7']

s = '#q1_a1'
print s[1:].split('_')
# ['q1', 'a1']

这是假设您所有的字符串都以#. 如果不是这种情况,那么您可以轻松地进行一些验证:

s = '#q1_a1'
if s.startswith('#'):
    print s[1:].split('_')
# ['q1', 'a1]

s = 'q1_a1'
if s.startswith('#'):
    print s[1:].split('_')  # Nothing is printed
于 2013-01-27T07:45:35.307 回答