Регулярное выражение Python для сопоставления, только если присутствует `=` - PullRequest
2 голосов
/ 29 октября 2019

У меня есть эти данные:

{{Character
| Title=Jhiqui
| Image=Jhiqui.png
}}

{{Ala|a;a}}

Я хочу написать регулярное выражение на python, которое соответствует содержанию внутри {{}} для первых данных, но ничего для вторых.

У меня есть это \{\{(.+?)\}\}, что с DOTALL соответствует содержанию обеих строк. Я хочу добавить что-то к регулярному выражению, которое требует, чтобы содержимое внутри {{}} содержало один или несколько =.

Как я могу это сделать?

Регулярное выражение, данное @heemayl, не соответствует следующему тексту:

{{Character\n| Title = Jon Snow\n| Image = Profile-JonSnow-707.png\n| Season = [[Season 1|1]], [[Season 2|2]], [[Season 3|3]], [[Season 4|4]], [[Season 5|5]], [[Season 6|6]], [[Season 7|7]], [[Season 8|8]]\n| First = "[[Winter is Coming (episode)|Winter is Coming]]"\n| Last = \n| Appearances =\n| Aka = Aegon Targaryen<br>Lord Snow<br>The Bastard of Winterfell<br>King Crow<br>[[The Prince That Was Promised]]<br>The White Wolf\n| Status = [[:Category: Living individuals|Alive]] <small>(resurrected)</small>\n| Titles = [[Warden|Warden of the North]] <br>[[King in the North]] <small>(formerly)</small><BR>\n998th [[Lord Commander of the Night\'s Watch]] <small>(formerly)</small>\n| Place = [[Tower of Joy]] <small>(birthplace)</small><br>[[Winterfell]] <small>(raised)</small>\n| Allegiance =  [[House Stark]]<br>[[House Targaryen]] <small>(by pledge)</small><br>The [[Night\'s Watch]] <small>(formerly)</small>\n| Family = \n| Lovers = [[Daenerys Targaryen]]<br>{[[Ygritte]]}\n| Religion = [[Old Gods of the Forest]]\n| Culture = [[Northmen]]<!--Please do not add "Valyrian" to his culture. Despite his blood, he was raised a Northman, without any knowledge of his heritage. This has been discussed and clarified, so insisting on it will be considered fanon and dealt with accordingly-->\n| Actor = [[Kit Harington]]\n| Age = 23 in Season 8<ref>Jon is roughly the same age as Robb Stark, and they were both born near the end of Robert\'s Rebellion - which in the novels was 15 years before the beginning of the narrative, so they were both about 14. In the TV version, the rebellion was 17 years ago, making Jon and Robb 16 in Season 1. Seven years pass in the TV series by Season 8.</ref>\n|Birth = Shortly after [[Robert\'s Rebellion]], [[Timeline#Robert\'s Rebellion|281 AC]]\n|Death = [[Timeline#Season 5 - 302 AC|302 AC]]<br>\nStabbed to death by his own men in the [[Mutiny at Castle Black]] <small>(later resurrected)</small>\n|DeathEp = [[Mother\'s Mercy]] <small>(soon after resurrected)</small>\n|Father = Biological:<br>\n{[[Rhaegar Targaryen]]}\n----\nAdoptive:<br>\n{[[Eddard Stark]]}\n|Mother = {[[Lyanna Stark]]}\n|Siblings = Paternal half-siblings:<br>\n{[[Rhaenys Targaryen (daughter of Rhaegar)|Rhaenys Targaryen]]}<br>\n{[[Aegon Targaryen (son of Rhaegar)|Aegon Targaryen]]} (son of Elia)\n----\nMaternal cousins raised as half-siblings:<br>\n{[[Robb Stark]]}<br>\n[[Sansa Stark]]<br>\n[[Arya Stark]]<br>\n[[Bran Stark]]<br>\n{[[Rickon Stark]]}<br>\n}}

Что должно быть сопоставлено и получаетсовпал с моим простым регулярным выражением, которое не проверяет =.

Есть идеи почему?

Ответы [ 4 ]

3 голосов
/ 29 октября 2019

Вы можете использовать:

\{\{([^}]*=[^}]*)\}\}

в многострочном режиме.

  • \{\{ соответствует {{ буквально
  • [^}]* соответствует нулюили более символов, которые не являются }, тогда = соответствует буквально
  • [^}]* снова соответствует нулю или более символов, которые не } и \}\} соответствуют }} буквально в конце
  • Содержимое внутри {{..}} будет доступно в единственной захваченной группе

In [125]: text = '''{{Character 
     ...: | Title=Jhiqui 
     ...: | Image=Jhiqui.png 
     ...: }} 
     ...:  
     ...: {{Ala|a;a}}'''                                                                                                                                                                                    

In [126]: re.search(r'\{\{([^}]*=[^}]*)\}\}', text, re.M)                                                                                                                                                     
Out[126]: <re.Match object; span=(0, 48), match='{{Character\n| Title=Jhiqui\n| Image=Jhiqui.png\n>

In [127]: re.search(r'\{\{([^}]*=[^}]*)\}\}', text, re.M).group()                                                                                                                                             
Out[127]: '{{Character\n| Title=Jhiqui\n| Image=Jhiqui.png\n}}'

In [128]: re.search(r'\{\{([^}]*=[^}]*)\}\}', text, re.M).group(1)                                                                                                                                          
Out[128]: 'Character\n| Title=Jhiqui\n| Image=Jhiqui.png\n'
2 голосов
/ 29 октября 2019

Я почти уверен, что вы даже хотите что-то сделать со значениями, поэтому напишите небольшой синтаксический анализатор, чтобы потом можно было с ним работать дальше:

import re
from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor

data = """
lorem ipsum

{{Character
| Title=Jhiqui
| Image=Jhiqui.png
}}

lorem ipsum dolor sit amet

{{Ala|a;a}}


"""
# the regex
rx = re.compile(r'\{\{.+?\}\}', re.DOTALL)

# the parser
class SomeVisitor(NodeVisitor):
    grammar = Grammar(
        r"""
        expr        = lpar tag ws? attr+ rpar
        attr        = delim ws+ word ws? equal ws? word ws?
        tag         = word+
        word        = ~"[.\w]+"
        delim       = "|"
        equal       = "="
        lpar        = "{{"
        rpar        = "}}"
        ws          = ~"\s+"
        """
    )

    def generic_visit(self, node, visited_children):
        return visited_children or node

    def visit_attr(self, node, visited_children):
        key = visited_children[2]
        value = visited_children[6]
        return (key.text, value.text)

    def visit_tag(self, node, visited_children):
        return node.text

    def visit_expr(self, node, visited_children):
        _, tag, _, attr, _ = visited_children
        return {tag: dict(attr)}


# invoke it
sv = SomeVisitor()

for m in rx.finditer(data):
    try:
        tag = sv.parse(m.group(0))
        print(tag)
    except:
        pass

Это дает

{'Character': {'Title': 'Jhiqui', 'Image': 'Jhiqui.png'}}
1 голос
/ 29 октября 2019

Вы можете использовать отрицательный класс символов и = внутри захваченного, чтобы убедиться, что он совпадает, только когда есть =

\{\{([^=]*=.*?)\}\}

enter image description here

Regex demo

1 голос
/ 29 октября 2019

Примерно так будет работать:

{{([^}=]+=.+?)}}

https://regex101.com/r/qhT7K0/1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...