Wie die Grammatik für diese in pyparsing schreiben: eine Reihe von Wörtern entsprechen, aber nicht auf ein bestimmtes Muster enthält,

StackOverflow https://stackoverflow.com/questions/1805309

  •  05-07-2019
  •  | 
  •  

Frage

Ich bin neu in Python und pyparsing. Ich brauche die folgenden zu erreichen.

Meine Probe Textzeile ist wie folgt:

12 items - Ironing Service    11 Mar 2009 to 10 Apr 2009
Washing service (3 Shirt)  23 Mar 2009

Ich brauche die Artikelbeschreibung zu extrahieren, Periode

tok_date_in_ddmmmyyyy = Combine(Word(nums,min=1,max=2)+ " " + Word(alphas, exact=3) + " " + Word(nums,exact=4))
tok_period = Combine((tok_date_in_ddmmmyyyy + " to " + tok_date_in_ddmmmyyyy)|tok_date_in_ddmmmyyyy)

tok_desc =  Word(alphanums+"-()") but stop before tok_period

Wie dies zu tun?

War es hilfreich?

Lösung

Ich würde vorschlagen, bei skipto als pyparsing Klasse suchen, der am besten geeignet ist, da man eine gute Definition des unerwünschten Textes hat, aber so ziemlich alles, bevor das akzeptieren. Hier sind ein paar Möglichkeiten, skipto zu verwenden:

text = """\
12 items - Ironing Service    11 Mar 2009 to 10 Apr 2009
Washing service (3 Shirt)  23 Mar 2009"""

# using tok_period as defined in the OP

# parse each line separately
for tx in text.splitlines():
    print SkipTo(tok_period).parseString(tx)[0]

# or have pyparsing search through the whole input string using searchString
for [[td,_]] in SkipTo(tok_period,include=True).searchString(text):
    print td

Beide for Schleifen drucken wie folgt vor:

12 items - Ironing Service    
Washing service (3 Shirt) 

Andere Tipps

M K Saravanan, dieses besondere Parsing Problem ist nicht so schwer, mit gutem ‚ole re zu tun:

import re
import string

text='''
12 items - Ironing Service    11 Mar 2009 to 10 Apr 2009
Washing service (3 Shirt)  23 Mar 2009
This line does not match
'''

date_pat=re.compile(
    r'(\d{1,2}\s+[a-zA-Z]{3}\s+\d{4}(?:\s+to\s+\d{1,2}\s+[a-zA-Z]{3}\s+\d{4})?)')
for line in text.splitlines():
    if line:
        try:
            description,period=map(string.strip,date_pat.split(line)[:2])
            print((description,period))
        except ValueError:
            # The line does not match
            pass

Ausbeuten

# ('12 items - Ironing Service', '11 Mar 2009 to 10 Apr 2009')
# ('Washing service (3 Shirt)', '23 Mar 2009')

Das Haupt Arbeitspferd hier ist natürlich das Wieder Muster. Lassen Sie uns brechen sie auseinander:

\d{1,2}\s+[a-zA-Z]{3}\s+\d{4} ist die regexp für ein Datum, das Äquivalent von tok_date_in_ddmmmyyyy. \d{1,2} für eine oder zwei Ziffern, \s+ für ein oder mehr Leerzeichen, Streichhölzer [a-zA-Z]{3} 3 Buchstaben, etc.

(?:\s+to\s+\d{1,2}\s+[a-zA-Z]{3}\s+\d{4})? ist ein regulärer Ausdruck von (?:...) umgeben. Dies deutet auf eine nicht-Gruppierung regexp. Unter Verwendung dieser, keine Gruppe (z.B. match.group (2)) ist diesem regexp zugeordnet. Dies ist wichtig, weil date_pat.split () gibt eine Liste mit jeder Gruppe ein Mitglied der Liste ist. Durch die Gruppierung unterdrücken, halten wir den gesamten Zeitraum 11 Mar 2009 to 10 Apr 2009 zusammen. Das Fragezeichen am Ende gibt an, dass dieses Muster null oder einmal auftreten kann. Dies ermöglicht es dem regexp beide übereinstimmen 23 Mar 2009 und 11 Mar 2009 to 10 Apr 2009.

text.splitlines() teilt Text auf \n.

date_pat.split('12 items - Ironing Service 11 Mar 2009 to 10 Apr 2009')

teilt den String auf der date_pat regexp. Das Spiel wird in der zurückgegebenen Liste enthalten. So erhalten wir:

['12 items - Ironing Service ', '11 Mar 2009 to 10 Apr 2009', '']

map(string.strip,date_pat.split(line)[:2]) verschönert das Ergebnis.

Wenn line nicht date_pat überein, date_pat.split(line) dann kehrt [line,], so

description,period=map(string.strip,date_pat.split(line)[:2])

wirft ein Valueerror, weil wir mit einer Liste nur ein Element in ein 2-Tupel nicht entpacken kann. Wir fangen diese Ausnahme aber einfach in der nächsten Zeile weitergeben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top