[英]Extracting name and number from string
与此问题类似,我有一串用冒号分隔的名称和数字:
s = 'Waz D: 5 l gu l: 5 GrinVe: 3 P LUK: 2 Cubbi: 1 2 nd dok: 1 maf 74: 1 abr12: 1 Waza D 5'
我正在尝试将其拆分为:
('Waz D', '5'),
('l gu l', '5'),
('GrinVe', '3'),
('P LUK', '2'),
('Cubbi', '1'),
('2 nd dok', '1')
('maf 74', '1')
('abr12', '1')
到目前为止,我已经尝试了两个正则表达式,但取得了不同的成功:
re.findall(r"(.*?)[a-zA-Z0-9]+: (\d+)*", s)
[('Waz ', '5'),
(' l gu ', '5'),
(' ', '3'),
(' P ', '2'),
(' ', '1'),
(' 2 nd ', '1'),
(' maf ', '1'),
(' ', '1')]
和:
re.findall(r"(.*?)([a-zA-Z0-9]+): (\d+)*", s)
[('Waz ', 'D', '5'),
(' l gu ', 'l', '5'),
(' ', 'GrinVe', '3'),
(' P ', 'LUK', '2'),
(' ', 'Cubbi', '1'),
(' 2 nd ', 'dok', '1'),
(' maf ', '74', '1'),
(' ', 'abr12', '1')]
我该如何调整以获得我想要的输出?
贪婪地使用空格,不要将其放入匹配的组中。
>>> import re
>>> s = 'Waz D: 5 l gu l: 5 GrinVe: 3 P LUK: 2 Cubbi: 1 2 nd dok: 1 maf 74: 1 abr12: 1 Waza D 5'
>>>
>>> re.findall('([^:]+?):\s*(\d+)\s*', s)
[('Waz D', '5'), ('l gu l', '5'), ('GrinVe', '3'), ('P LUK', '2'), ('Cubbi', '1'), ('2 nd dok', '1'), ('maf 74', '1'), ('abr12', '1')]
如果我们假设字符串始终后面跟有分号-空格-数字-空格序列,则可以这样执行:
re.findall(r"(.+?):\s(\d+)\s", s)
[('Waz D', '5'),
('l gu l', '5'),
('GrinVe', '3'),
('P LUK', '2'),
('Cubbi', '1'),
('2 nd dok', '1'),
('maf 74', '1'),
('abr12', '1')]
归结为对组合的分割: \\d
,除此之外(除了在此处和此处抑制前导空格和后跟空格)。 它需要的是一个不包含冒号:
的任意长度的组,其后是该冒号,然后是一串数字。
import re
s = 'Waz D: 5 l gu l: 5 GrinVe: 3 P LUK: 2 Cubbi: 1 2 nd dok: 1 maf 74: 1 abr12: 1 Waza D 5'
print (re.findall(r'([^:]+):\s*(\d+)\s+', s))
结果:
[('Waz D', '5'),
('l gu l', '5'),
('GrinVe', '3'),
('P LUK', '2'),
('Cubbi', '1'),
('2 nd dok', '1'),
('maf 74', '1'),
('abr12', '1')]
您可以匹配零次或多次匹配空白字符,然后使用否定的字符类([^:]+)
其捕获为一组而不是冒号。
然后匹配一个冒号,零个或多个空格字符\\s*
并捕获一组一个或多个数字(\\d+)
在您的样本中,名称通常以字母开头,但在一种情况下-以数字开头。
因此,第一个捕获组的名称应为:
[az\\d]
re.I
(记住re.I
处的re.I
标志), [^:]*
-除:
以外的一系列字符。 您的解决方案( [a-zA-Z0-9]+
)错误,因为名称可以包含空格。
第二组,与数字匹配很简单- \\d+
。
在这两个组之间应该有:\\s*
-一个冒号和一系列白色字符。
该代码包含对re.findall
的单个调用,如下所示:
re.findall(r"([a-z\d][^:]*):\s*(\d+)", s, flags=re.I)
但我对Cubbi: 1 2
感到怀疑Cubbi: 1 2
您的样本中Cubbi: 1 2
。 如若2
真的是下一个名称的一部分?
如果不是,请考虑将正则表达式更改为: ([az][^:]*):\\s*(\\d+(?: \\d+)?)
。 差异:
(?: \\d+)?
。 然后1 2
将是Cubbi的“数字”,并且下一个名称将从“ nd”开始。
样品末尾的Waza D 5
呢? 您是否忘记将冒号放在5
之前?
我在Waza D之后添加了“:”,因为我认为应该是(我认为这是一个错字,因为规则应该是name:number)。 对我而言, 模式是一个以字母开头的名称,然后是其他字母/数字和空格,直到::一个空格和一个数字。
s = 'Waz D: 5 l gu l: 5 GrinVe: 3 P LUK: 2 Cubbi: 1 2 nd dok: 1 maf 74: 1 abr12: 1 Waza D: 5'
import re
# \w find something starting with a letter
# [\w\s]+ followed by any number of letter and space
# : followed by a :
# \s[0-9] and a space and a number
x = re.findall(r"\w[\w\s]+:\s[0-9]", s)
print(*x, sep="\n")
输出
Waz D: 5
l gu l: 5
GrinVe: 3
P LUK: 2
Cubbi: 1
2 nd dok: 1
maf 74: 1
abr12: 1
Waza D: 5
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.