从字符串中提取名称和编号

问题描述 投票:1回答:6

this question类似,我有一串由冒号分隔的名称和数字:

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')]

如何调整此项以获得我之后的输出?

python regex
6个回答
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')]

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')]

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')]

1
投票

您可以匹配空白字符的零次或多次,然后使用否定的字符类([^:]+)捕获组而不是冒号。

然后匹配一个冒号,零个或多个空白字符\s*并捕获一组或多组数字(\d+)

\s*([^:]+):\s*(\d+)

Demo


0
投票

在您的示例中,名称通常从一个字母开始,但在1个案例中 - 从一个数字开始。

所以第一个捕获组,名称应该:

  • [a-z\d]开始(最后记得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表示怀疑。 2真的应该成为下一个名字的一部分吗?

如果没有,请考虑将正则表达式更改为:([a-z][^:]*):\s*(\d+(?: \d+)?)。区别:

  • 名称必须以字母(不是数字)开头,
  • 该数字可以包含“第二部分”,前面有一个空格 - (?: \d+)?

然后1 2将成为Cubbi的“数字”,下一个名字将从“nd”开始。

那么样品末尾的Waza D 5呢?你忘了把结肠放在5之前吗?


0
投票

我的解决方案

我在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
© www.soinside.com 2019 - 2024. All rights reserved.