[英]Regex for extraction in Python
我有一个像这样的字符串:
"a word {{bla|123|456}} another {{bli|789|123}} some more text {{blu|789}} and more".
我想得到这个作为输出:
(("bla", 123, 456), ("bli", 789, 123), ("blu", 789))
我还没有找到合适的python正则表达式来实现这一目标。
自{
, }
和|
,您需要在正则表达式中进行很多转义。 是其中的特殊字符。 提取字符串相关部分的第一步是:
regex = re.compile(r'\{\{(.*?)\|(.*?)(?:\|(.*?))?\}\}')
regex.findall(line)
对于此示例,它给出:
[('bla', '123', '456'), ('bli', '789', '123'), ('blu', '789', '')]
然后,您可以继续将带有数字的字符串转换为整数,并删除空字符串,例如最后一次匹配。
>>> re.findall(' {{(\w+)\|(\w+)(?:\|(\w+))?}} ', s)
[('bla', '123', '456'), ('bli', '789', '123'), ('blu', '789', '')]
如果仍然需要数字,则需要对输出进行迭代,并使用int
将其转换为整数。
[re.split('\|', i) for i in re.findall("{{(.*?)}}", str)]
返回:
[['bla', '123', '456'], ['bli', '789', '123'], ['blu', '789']]
无论{{}}块中元素的数量如何,此方法都有效。
为了获得您编写的确切输出,您需要一个正则表达式和一个分割:
import re
map(lambda s: s.split("|"), re.findall(r"\{\{([^}]*)\}\}", s))
要获取转换后的数字,请执行以下操作:
toint = lambda x: int(x) if x.isdigit() else x
[map(toint, p.split("|")) for p in re.findall(r"\{\{([^}]*)\}\}", s)]
我们也许可以花哨的钱就可以用一个复杂的正则表达式来做所有事情,但这就是疯狂。 让我们做一个正则表达式来获取组,然后将组拆分。 我们可以使用正则表达式来拆分组,但是我们可以只使用str.split(),所以让我们这样做。
import re
pat_group = re.compile("{{([^}]*)}}")
def mixed_tuple(iterable):
lst = []
for x in iterable:
try:
lst.append(int(x))
except ValueError:
lst.append(x)
return tuple(lst)
s = "a word {{bla|123|456}} another {{bli|789|123}} some more text {{blu|789}} and more"
lst_groups = re.findall(pat_group, s)
lst = [mixed_tuple(x.split("|")) for x in lst_groups]
在pat_group中,“ {{”仅匹配文字“ {{”。 “(”开始一个组。“ [^}]”是一个字符类,它匹配除“}”以外的任何字符,并且'*'允许它匹配零个或多个这样的字符。“)”关闭该组,而“ }}“匹配文字字符。 因此,我们匹配“ {{......}}”模式,并且可以将花括号之间的所有内容作为一个组提取。
re.findall()返回与模式匹配的组列表。
最后,列表推导拆分每个字符串,并将结果作为元组返回。
假设您的实际格式为{{[az]+|[0-9]+|[0-9]+}}
,这是一个完整的程序,可以转换为整数。
import re
s = "a word {{bla|123|456}} another {{bli|789|123}} some more text {{blu|789}} and more"
result = []
for match in re.finditer('{{.*?}}', s):
# Split on pipe (|) and filter out non-alphanumerics
parts = [filter(str.isalnum, part) for part in match.group().split('|')]
# Convert to int when possible
for index, part in enumerate(parts):
try:
parts[index] = int(part)
except ValueError:
pass
result.append(tuple(parts))
pyparsing为此过度杀伤力? 也许可以,但不会带来太大的痛苦,它确实可以提供所需的输出,而不会产生反斜杠,以逃避'{','|'或'}'字符。 另外,不需要进行整数后解析转换,而是在解析时执行解析操作。
from pyparsing import Word, Suppress, alphas, alphanums, nums, delimitedList
LBRACE,RBRACE,VERT = map(Suppress,"{}|")
word = Word(alphas,alphanums)
integer = Word(nums)
integer.setParseAction(lambda t: int(t[0]))
patt = (LBRACE*2 + delimitedList(word|integer, VERT) + RBRACE*2)
patt.setParseAction(lambda toks:tuple(toks.asList()))
s = "a word {{bla|123|456}} another {{bli|789|123}} some more text {{blu|789}} and more"
print tuple(p[0] for p in patt.searchString(s))
打印:
(('bla', 123, 456), ('bli', 789, 123), ('blu', 789))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.