python 正则表达式 - 可选匹配
我有一堆字符串,它们的格式是这样的:
#q1_a1
#q7
基本上,#这个符号是需要忽略的。
在#后面,会跟着一个字母和一些数字。
另外,_
(下划线)后面可以跟一些字母和数字的组合。
这是我想到的解决办法:
>>> pat = re.compile(r"#(.*)_?(.+)?")
>>> pat.match('#q1').groups()
('q1', None)
问题出在格式为#q1_a1
的字符串上。当我把我想出来的方法应用到这样的字符串时:
>>> pat.findall('#q1_f1')
[('q1_f1', '')]
有没有什么建议呢?
4 个回答
2
你的“.*”这个表达式会把下划线也匹配上,因为它是贪婪匹配。更好的做法是写一个更具体的正则表达式,这样可以把下划线排除在第一个匹配组之外。
一个合适的正则表达式可能长这样:
#([a-z][0-9])_?([a-z][0-9])?
不过你需要检查一下,这个表达式是否适用于你所有预期的数据。
另外,正则表达式越具体越好,这样可以减少错误匹配的情况。
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)
注意事项:
- 如果你只想匹配整个字符串,可以在正则表达式的前面加上
^
,在后面加上$
。 - 你提到“某个数字”,但你的例子只包含一个数字。如果你的正则表达式需要接受多个数字,可以把
[0-9]
改成[0-9]+
。
1
当你使用 .*
时,它会尽可能多地匹配内容,这种匹配方式叫做 贪婪匹配。你可以试试:
>>> pat = re.compile(r"#([^_]*)_?(.+)?")
>>> pat.findall('#q1_f1')
[('q1', 'f1')]
另外,写一个更具体的表达式会更好:
#([a-z][0-9])(?:_([a-z][0-9]))?