python regex mediawiki节解析

2024-10-03 06:25:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我有类似以下文字:

==Mainsection1==  
Some text here  
===Subsection1.1===  
Other text here  

==Mainsection2==  
Text goes here  
===Subsecttion2.1===  
Other text goes here. 

在上面的文本中,主要部分1和2有不同的名称,可以是任何用户想要的。小节也是如此。在

我想对regex做的是获取一个主要部分的文本,包括它的子部分(如果有的话)。 是的,这是一个维基页面。所有主要部分的名称以==开头,以==结尾 所有子部分的名称都大于2==。在

^{pr2}$

但是上面的返回每个单独的部分。 这意味着它完全返回了一个mainsection,但是它自己看到了一个小节。在

我希望有人能帮我解决这个问题,因为它困扰了我一段时间

编辑: 结果应该是:

[('Mainsection1', 'Some text here\n===Subsection1.1===  
Other text here\n'), ('Mainsection2', 'Text goes here\n===Subsecttion2.1===  
Other text goes here.\n')]

编辑2:
我重写了我的代码以不使用regex。我得出的结论是,只要自己解析它就足够容易了。这让我更容易阅读。在

下面是我的代码:

def createTokensFromText(text):    
    sections = []
    cur_section = None
    cur_lines = []


    for line in text.split('\n'):
        line = line.strip()
        if line.startswith('==') and not line.startswith('==='):
            if cur_section:
                sections.append( (cur_section, '\n'.join(cur_lines)) )
                cur_lines = []
            cur_section = line
            continue
        if cur_section:
            cur_lines.append(line)

    if cur_section:
        sections.append( (cur_section, '\n'.join(cur_lines)) )
    return sections

谢谢大家的帮助!在

所有提供的答案对我帮助很大!


Tags: text名称ifherelinesectionsomelines
2条回答

首先,应该知道,我对Python有一点了解,但我从来没有用它正式编程。。。Codepad说这行得通,所以开始吧!:D抱歉,表达式太复杂:

(?<!=)==([^=]+)==(?!=)([\s\S]*?(?=$|(?<!=)==[^=]+==(?!=)))

我相信这符合你的要求!在代码板上,this code

^{pr2}$

产生以下结果:

[('Mainsection1', '\nSome text here\n===Subsection1.1===\nOther text here\n\n'), ('Mainsection2', '\nText goes here\n===Subsecttion2.1===\nOther text goes here. ')]

编辑:分解后,表达式基本上是这样说的:

01 (?<!=)        # First, look behind to assert that there is not an equals sign
02 ==            # Match two equals signs
03 ([^=]+)       # Capture one or more characters that are not an equals sign
04 ==            # Match two equals signs
05 (?!=)         # Then verify that there are no equals signs following this
06 (             # Start a capturing group
07   [\s\S]*?    #   Match zero or more of ANY character (even CrLf), but BE LAZY
08   (?=         #   Look ahead to verify that either...
09     $         #     this is the end of the 
10     |         #     -OR-
11     (?<!=)    #     when I look behind there is no equals sign
12     ==        #     then there are two equals signs
13     [^=]+     #     then one or more characters that are not equals signs
14     ==        #     then two equals signs
15     (?!=)     #     then verify that there are no equals signs following this
16   )           #   End look-ahead group
17 )             # End capturing group 

03行和第06行分别指定主节标题和主节内容的捕获组。在

如果您对Regex不太流利,第07行需要大量的解释。。。在

  • 字符类中的\s和{}将匹配任何空白或非空白的内容(即任何内容)——一种替代方法是使用.运算符,但这取决于编译器的选项(或指定选项的能力),这可能与CrLf(或回车符/换行符)匹配,也可能不匹配。由于要匹配多行,这是确保匹配的最简单方法。在
  • 结尾的*?意味着它将匹配“anything”字符类的零个或多个实例,但要对其懒惰-“LAZY”量词(有时称为“discious”)与默认的“greedy”量词相反(后面没有?),并且不会使用源字符,除非紧随其后的源无法与紧跟在lazy量词后面的表达式部分匹配。换句话说,它将使用任何字符,直到它找到源文本的结尾或另一个主要部分,而另一个主要部分是由两个且只有两个等号指定的,在一个或多个不是等号(包括空白)的字符的任一侧。如果没有lazy运算符,它将尝试使用整个源文本,然后“回溯”直到它可以匹配表达式中它后面的某个内容(源代码结尾或节头)

08行是一个“前瞻”,它指定后面的表达式应该能够匹配,但不应该被使用。在

结束编辑

阿飞,它必须是如此复杂,以便正确地排除这些小节。。。如果要将节名称和节内容匹配到命名组中,可以尝试以下操作:

(?<!=)==(?P<SectionName>[^=]+)==(?!=)(?P<SectionContent>[\s\S]*?(?=$|(?<!=)==[^=]+==(?!=)))

如果你愿意的话,我可以帮你分解一下!就问吧!编辑(参见上面的编辑)结束编辑

这里的问题是^{cd1>}匹配^{cd2>},因此,首先要做的是确保标题:^{{cd4>}内没有^{cd3>}。

然后,我们需要确保在比赛开始之前没有^{{cd3>},否则,忽略三个选项中的第一^{{cd3>}并且匹配字幕。这将实现这样的技巧:^{{cd7>},它意味着“匹配,如果前面没有…”。

我们也可以在最后完成这项工作,以确保最终结果^{{cd8>}。

>>> re.findall('(?<!=)==([^=]*)==(?!=)([^=]*)', x,re.MULTILINE)
[('Mainsection1', '\nSome text here\n'),
 ('Mainsection2', '\nText goes here\n')]

您还可以删除标题末尾的检查,并将其替换为换行。如果你确定每一个标题的结尾都有一行新行,那可能会更好。

^{pr2}$

编辑:

^{pr3}$

它比看上去简单:反复地,我们在前一个标题之后搜索一个节标题,并将其添加到结果中,文本介于此标题的开头和前一个标题的结尾之间。调整它以适应你的风格和你的需要。结果是:

^{pr4}$

相关问题 更多 >