Python没有提取预期的模式
Posted
技术标签:
【中文标题】Python没有提取预期的模式【英文标题】:Python Not Extracting Expected Pattern 【发布时间】:2017-12-21 07:36:55 【问题描述】:我是 RegEx 的新手,我正在尝试执行一个简单的匹配以使用 re.findall 提取项目列表。但是,我没有得到预期的结果。你能帮忙解释一下为什么我还根据下面的正则表达式模式获得了这个字符串的第一部分,以及我需要修改什么以获得所需的输出吗?
import re
string = '''aaaa_1y345_xyz_orange_bar_1
aaaa_123a5542_xyz_orange_bar_1
bbbb_1z34512_abc_purple_bar_1'''
print(re.findall('_\w+_\w+_bar_\d+', string))
电流输出:
['_1y345_xyz_orange_bar_1', '_123a5542_xyz_orange_bar_1', '_1z34512_abc_purple_bar_1']
期望的输出:
['_xyz_orange_bar_1', '_xyz_orange_bar_1', '_abc_purple_bar_1']
【问题讨论】:
【参考方案1】:\w
模式匹配字母、数字和 _
符号。根据使用的 Python 版本和选项,它可以匹配的字母和数字可能来自整个 Unicode 范围或只是 ASCII。
因此,解决此问题的最佳方法是将\w
替换为[^\W_]
:
import re
string = '''aaaa_1y345_xyz_orange_bar_1
aaaa_123a5542_xyz_orange_bar_1
bbbb_1z34512_abc_purple_bar_1'''
print(re.findall(r'_[^\W_]+_[^\W_]+_bar_[0-9]+', string))
# => ['_xyz_orange_bar_1', '_xyz_orange_bar_1', '_abc_purple_bar_1']
请参阅Python demo。
详情:
_
- 下划线
[^\W_]+
- 1 个或多个数字或字母字符([^
启动否定字符类,\W
匹配任何非单词字符,并且添加 _
以匹配除 @987654333 之外的任何单词字符@)
_[^\W_]+
- 同上
_bar_
- 文字子字符串 _bar_
[0-9]+
- 1 个或多个 ASCII 数字。
请参阅regex demo。
【讨论】:
感谢您的详细解释。【参考方案2】:_[a-z]+_\w+_bar_\d+
应该可以工作。
import re
string = '''aaaa_1y345_xyz_orange_bar_1
aaaa_123a5542_xyz_orange_bar_1
bbbb_1z34512_abc_purple_bar_1'''
print(re.findall('_[a-z]+_\w+_bar_\d+', string))
o/p
['_xyz_orange_bar_1', '_xyz_orange_bar_1', '_abc_purple_bar_1']
【讨论】:
【参考方案3】:您的问题是正则表达式是贪婪的,并试图尽可能多地匹配。有时可以通过在+
(加号)后添加?
(问号)来解决此问题。但是,在您当前的解决方案中这是不可行的(至少以任何简单的方式 - 它可能通过一些前瞻来完成)。但是,您可以选择另一种模式,明确禁止匹配 _
(下划线)字符为:
import re
string = '''aaaa_1y345_xyz_orange_bar_1
aaaa_123a5542_xyz_orange_bar_1
bbbb_1z34512_abc_purple_bar_1'''
print(re.findall('_[^_\W]+_[^_\W]+_bar_\d+', string))
这将符合您的期望。 [^ ... ]
结构的意思是 not,因此不是下划线,也不是 not whitespace。
【讨论】:
【参考方案4】:您的代码的问题是\w
模式等效于以下字符集:[a-zA-Z0-9_]
我猜你需要匹配相同的集合但没有下划线:
import re
string = '''aaaa_1y345_xyz_orange_bar_1
aaaa_123a5542_xyz_orange_bar_1
bbbb_1z34512_abc_purple_bar_1'''
print(re.findall('_[a-zA-Z0-9]+_[a-zA-Z0-9]+_bar_\d+', string))
输出:
['_xyz_orange_bar_1', '_xyz_orange_bar_1', '_abc_purple_bar_1']
【讨论】:
【参考方案5】:您对\w
的使用过于宽松。它不仅可以找到字母,还可以找到数字和下划线。来自docs:
当没有指定 LOCALE 和 UNICODE 标志时,匹配任何字母数字字符和下划线;这相当于集合
[a-zA-Z0-9_]
。使用 LOCALE,它将匹配集合[0-9_]
加上任何被定义为当前语言环境的字母数字字符。如果设置了 UNICODE,这将匹配字符[0-9_]
加上 Unicode 字符属性数据库中归类为字母数字的任何内容。
取而代之的是我们要匹配的实际字符分组。
_[a-z]+_[a-z]+_bar_[0-9]+
如果确实需要\w
不带下划线的完全匹配,可以将字符分组改为:
[a-zA-Z0-9]
【讨论】:
string
?从什么时候开始?
string
是标准库模块的名称,但可以安全地用作变量名。
无论如何,最好以事物的本质而非类型命名,以避免任何可能的冲突。以上是关于Python没有提取预期的模式的主要内容,如果未能解决你的问题,请参考以下文章