Elemente aus einem Muster heraus analysieren

  • Ich versuche, die Ergebnisausgabe eines Parsers mit natürlicher Sprache (Stanford-Parser) zu analysieren. Einige Ergebnisse sind wie folgt:

     dep(Company-1, rent-5')
    conj_or(rent-5, share-10)
    amod(information-12, personal-11)
    prep_about(rent-5, you-14)
    amod(companies-20, non-affiliated-19)
    aux(provide-23, to-22)
    xcomp(you-14, provide-23)
    dobj(provide-23, products-24)
    aux(requested-29, 've-28)
     

    Das Ergebnis, das versucht wird, ist:

     ['dep', 'Company', 'rent']
    ['conj_or', 'rent', 'share']
    ['amod', 'information', 'personal']
    ...
    ['amod', 'companies', 'non-affiliated']
    ...
    ['aux', 'requested', "'ve"]
     

    Zuerst habe ich versucht, diese Elemente direkt herauszubekommen, ist aber gescheitert. Dann wurde mir klar, dass Regex der richtige Weg sein sollte.

    Allerdings bin ich völlig ungewohnt mit Regex. Bei einigen Recherchen bekam ich:

     m = re.search('(?<=())\w+', line)
    m2 =re.search('(?<=-)\d', line)
     

    und blieb hängen.

    Der erste kann die ersten Elemente korrekt erhalten, z 'dep', 'amod', 'conj_or', aber ich habe nicht wirklich herausgefunden, warum es funktioniert ...

    Zweite Zeile versucht, die zweiten Elemente zu erhalten, z.B 'Company', 'rent', 'information', aber ich kann nur die Zahl nach dem Wort erhalten. Ich kann nicht herausfinden, wie ich vor dem Schauen zurückschaue ...

    Übrigens, ich kann auch nicht herausfinden, wie ich mit Ausnahmen wie 'non-affiliated' und "'ve" umgehen soll. p>

    Könnte jemand Hinweise oder Hilfe geben? Sehr geschätzt.

    22 November 2011
    Flake
3 answers
  • Wenn die Ergebnisse des Parsers so regelmäßig sind, wie vorgeschlagen, sind Regexes möglicherweise nicht erforderlich:

     from pprint import pprint
    
    source = """
    dep(Company-1, rent-5')
    conj_or(rent-5, share-10)
    amod(information-12, personal-11)
    prep_about(rent-5, you-14)
    amod(companies-20, non-affiliated-19)
    aux(provide-23, to-22)
    xcomp(you-14, provide-23)
    dobj(provide-23, products-24)
    aux(requested-29, 've-28)
    """
    
    items = []
    
    for line in source.splitlines():
        head, sep, tail = line.partition('(')
        if head:
            item = [head]
            head, sep, tail = tail.strip('()').partition(', ')
            item.append(head.rpartition('-')[0])
            item.append(tail.rpartition('-')[0])
            items.append(item)
    
    pprint(items)
     

    Ausgabe:

     [['dep', 'Company', 'rent'],
     ['conj_or', 'rent', 'share'],
     ['amod', 'information', 'personal'],
     ['prep_about', 'rent', 'you'],
     ['amod', 'companies', 'non-affiliated'],
     ['aux', 'provide', 'to'],
     ['xcomp', 'you', 'provide'],
     ['dobj', 'provide', 'products'],
     ['aux', 'requested', "'ve"]]
     
    22 November 2011
    ekhumoro
  • Hier ist etwas, wonach Sie suchen: ([\w-]*)\(([\w-]*)-\d*, ([\w-]*)-\d*\)

    Die Klammern um [\w-]* dienen zum Gruppieren, sodass Sie auf Daten zugreifen können als:

     ex = r'([\w-]*)\(([\w-]*)-\d*, ([\w-]*)-\d*\)'
    m = re.match(ex, line)
    print(m.group(0), m.group(1), m.group(2))
     

    Übrigens empfehle ich die Verwendung des in Python + PyQT geschriebenen Programms "Kodos", um regelmäßig zu lernen und zu testen Ausdrücke. Es ist mein Lieblingswerkzeug, um Regex zu testen.

    22 November 2011
    Zaur Nasibov
  • Es ist schwierig, eine optimale Antwort zu geben, ohne den gesamten Bereich der möglichen Ausgaben zu kennen. Hier ist jedoch eine mögliche Lösung:

     >>> [re.findall(r'[A-Za-z_\'-]+[^-\d\(\)\']', line) for line in s.split('\n')]
    [['dep', 'Company', 'rent'], 
     ['conj_or', 'rent', 'share'], 
     ['amod', 'information', 'personal'], 
     ['prep_about', 'rent', 'you'], 
     ['amod', 'companies', 'non-affiliated'], 
     ['aux', 'provide', 'to'], 
     ['xcomp', 'you', 'provide'], 
     ['dobj', 'provide', 'products'], 
     ['aux', 'requested', "'ve"]]
     

    Sie finden alle Gruppen benachbarter Buchstaben ([A-Za-z] stehen für das Intervall zwischen Großbuchstaben A und Z und kleinem a und z) oder den Zeichen "_" und "'" line.

    Erzwingt außerdem die Regel, dass Ihre übereinstimmende Zeichenfolge an der letzten Stelle keine bestimmte Liste von Zeichen enthalten darf ([^...] ist die Syntax, um zu sagen, "darf keine enthalten der Zeichen (ersetzen Sie "..." durch die Liste der Zeichen)).

    Das Zeichen \ entfernt die Zeichen wie "(" oder ")", die andernfalls auftreten würden Von der Regex-Engine als Anweisungen analysiert werden.

    Schließlich ist s der Beispielstring, den Sie in der Frage angegeben haben ...

    HTH!

    22 November 2011
    macfrank