Python正则表达式在一行中找到两个关键字

时间:2009-12-28 15:38:12

标签: python regex findall

我很难理解这个正则表达式的东西......

我有一个这样的字符串:

<wn20schema:NounSynset rdf:about="&dn;synset-56242" rdfs:label="{saddelmageri_1}">

我想使用findall()和groups来获取:

['56242','saddelmageri']

我可以将数字与“synset- [0-9]”和“{(。*?)}”之类的单词匹配,但如何编写它以获得上述结果?

这是一个后续问题 - 有些行看起来像这样:

<wn20schema:NounSynset rdf:about="&dn;synset-2589" rdfs:label="**{cykel_3: trehjulet cykel; tricykel,1_1}**">

在这种情况下,我想在{}之间提取这个结果:

['2589', ['cykel', 'trehjulet cykel', 'tricykel']]

这样我以后就可以把它作为一个键(2589)放入字典中:value(['cykel','trehjulet cykel','tricykel'])对。

有什么想法吗?

4 个答案:

答案 0 :(得分:2)

请参阅this question最佳答案。用正则表达式解析xml通常是一个糟糕的主意。 XML解析器是为此目的而构建的。

最快的方法可能是python的built-in minidom

答案 1 :(得分:1)

由于这似乎是xml数据,因此最好使用xml解析器,因为使用正则表达式解析xml非常非常难以正确执行。

但是,因为你特意要求正则表达式......

您的规格有点不精确,使用正则表达式时,您需要非常精确地确定匹配的内容。例如,rdfs:label值是否始终具有要剥离的_1?是否每行只有一个这样的数据块,或每行多个?此外,结果的顺序是否重要?

这是一个快速的黑客攻击,可能会让你接近你想要的东西:

import re
data=r'<wn20schema:NounSynset rdf:about="&dn;synset-56242" rdfs:label="{saddelmageri_1}">"'

matches=re.findall('synset-([0-9]+).*label="{(.*)_1}"', data)
print "matches:", matches

当我运行上面的代码时,我得到以下输出,这是一个包含你想要的两个字符串的两元组列表(虽然顺序不同):

matches: [('56242', 'saddelmageri')]

答案 2 :(得分:1)

如果您对这些数据做了很多,请考虑使用专门的RDF库(例如RDFLib)。 如果没有,那么XML解析器绝对是最佳选择!

  • 如果明天它不会在一条线上怎么办?
  • 如果明天label将在about之前?
  • ,该怎么办?
  • 至少还有十几种方法可以保持有效的XML但打破你的正则表达式!

无论如何,我尝试应用XML解析器,但我在那里得到&dn;的“未定义的实体错误”。你可以发布文件的顶部(doctype,命名空间定义等)吗?

答案 3 :(得分:1)

你在这里做了两种不同的解析,你需要使用两种不同的工具。

首先,您正在解析XML。为此,您将需要使用XML解析器,而不是正则表达式。因为这些元素在功能上是相同的XML:

<wn20schema:NounSynset rdf:about="&dn;synset-56242" rdfs:label="{saddelmageri_1}">
</wn20schema:NounSysnset>

<wn20schema:NounSynset rdf:about="&dn;synset-56242" rdfs:label="{saddelmageri_1}"/>

<wn20schema:NounSynset rdfs:label="{saddelmageri_1}" rdf:about="&dn;synset-56242"/>

甚至可以说:

<NounSynset xmlns="my_wn20schema_namespace_urn" C:label='not_of_interest' A:label='{saddelmageri_1}' B:about='&dn;synset-56242'/>

要解析该元素,您需要知道您感兴趣的元素和属性所属的命名空间的名称,然后使用XML解析器来查找它们 - 特别是,正确支持XML的XML解析器名称空间和XPath,如lxml

你最终会得到这样的东西来找到你正在寻找的属性(假设doc是解析的XML文档,而以_urn结尾的变量是包含各种各样的字符串名称空间URN):

def find_attributes(doc):
    for elm in doc.xpath('//x:NounSynset', namespaces={'x': wn20schema_namespace_urn}):
        yield (elm.get(rdf_namespace_urn + "about"), elm.get(rdfs_namespace_urn + "label"))

现在您可以查看问题的第二部分,即从您拥有的属性值中解析所需的值。为此,您将使用正则表达式。要解析about属性,这可能有效:

re.match(r'[^\d]*(\d*)', about).groups()[0]

返回找到的第一个数字字符系列。要解析label属性,您可以使用:

re.match(r'{([^_]*)', label).groups()[0]

返回前导左括号后的label中的所有字符,但不包括第一个下划线。 (至于解析你发布的label的第二种形式,你还没有发布足够的信息来猜测要解析的正则表达式是什么样的。)