Frage

Dieser Code funktioniert:

from pyparsing import *

zipRE = "\d{5}(?:[-\s]\d{4})?" 
fooRE = "^\!\s+.*"

zipcode = Regex( zipRE )
foo = Regex( fooRE )

query = ( zipcode | foo )



tests = [ "80517", "C6H5OH", "90001-3234", "! sfs" ]

for t in tests:
    try:
        results = query.parseString( t )
        print t,"->", results
    except ParseException, pe:
        print pe

Ich bin fest auf zwei Fragen:

1 - Wie eine benutzerdefinierte Funktion verwenden, um ein Token zu analysieren. Zum Beispiel, wenn ich, wenn eine Zahl ist ein zipcode einig benutzerdefinierte Logik statt einem regulären Ausdruck zu bestimmen, verwenden wollte. Statt:

zipcode = Regex( zipRE )

vielleicht:

zipcode = MyFunc()

2 - Wie kann ich bestimmen, was ein String parst TO. „80001“ parst zu „zipcode“ aber wie kann ich feststellen, dies mit pyparsing? Ich bin nicht eine Zeichenfolge, für deren Richtigkeit Parsen, sondern einfach, um zu bestimmen, welche Art von Abfrage ist.

War es hilfreich?

Lösung

Ihre zweite Frage ist einfach, also werde ich das erste beantworten. Ändern Abfrage zu den Ergebnissen Namen zu den verschiedenen Ausdrücke zuweisen:

query = ( zipcode("zip") | foo("foo") ) 

Jetzt können Sie getName () auf dem zurückgegebenen Ergebnis nennen:

print t,"->", results, results.getName()

Giving:

80517 -> ['80517'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['90001-3234'] zip
! sfs -> ['! sfs'] foo

Wenn Sie vorhaben, das Ergebnis des fooness oder zipness zu verwenden, eine andere Funktion aufrufen, dann könnte man dies zur Analysezeit tun, um eine Parse-Aktion auf Ihre foo und zipcode Ausdrücke Befestigung:

# enclose zipcodes in '*'s, foos in '#'s
zipcode.setParseAction(lambda t: '*' + t[0] + '*')
foo.setParseAction(lambda t: '#' + t[0] + '#')

query = ( zipcode("zip") | foo("foo") ) 

Jetzt gibt:

80517 -> ['*80517*'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['*90001-3234*'] zip
! sfs -> ['#! sfs#'] foo

Für Ihre erste Frage, ich weiß nicht genau, welche Art von Funktion, die Sie bedeuten. Pyparsing bietet viele mehr Parsing Klassen als nur Regex (wie Word, Stichwort, Literal, CaselessLiteral), und Sie Ihren Parser komponieren, indem sie mit '+' Kombination '|', '^', '~', '@' und '*' Operatoren. Zum Beispiel, wenn Sie für eine US-Sozialversicherungsnummer, aber nicht verwenden, um eine Regex analysieren wollen, könnten Sie verwenden:

ssn = Combine(Word(nums,exact=3) + '-' + 
        Word(nums,exact=2) + '-' + Word(nums,exact=4))

Wortspiele für zusammenhängende „Worte“, bestehend aus dem gegebenen Zeichen in seinem Konstruktor, Kombinieren verkettet die angepassten Token in ein einziges Token.

Wenn Sie für eine mögliche Liste solcher Zahlen analysieren wollen, getrennt durch ‚/‘ s, zu verwenden:

delimitedList(ssn, '/')

oder wenn es zwischen 1 und 3, wie Zahlen, ohne delimters, zu verwenden:

ssn * (1,3)

Und jeder Ausdruck kann Ergebnisse Namen haben oder Aktionen mit ihnen verbunden analysieren, um weiter die analysierten Ergebnisse zu bereichern, oder die Funktionalität während der Analyse. Sie können sogar rekursive Parser, wie verschachtelte Listen von Klammern, arithmetische Ausdrücke bauen, etc., um die Vorwärts-Klasse.

Meine Absicht, als ich pyparsing schrieb, war, dass diese Zusammensetzung von Parsern von grundlegenden Bausteinen die primäre Form zum Erstellen eines Parsers sein würde. Erst in einer späteren Version, die ich hinzugefügt Regex als (was ich aber) die ultimative Flucht Ventil - wenn die Menschen ihre Parser nicht bauen könnte, könnten sie auf regex das Format zurückgreifen, die im Laufe der Zeit auf jeden Fall bewährt hat seine Macht.

Oder, wie ein anderes Plakat schon sagt, können Sie die pyparsing Quelle öffnen und Unterklasse eine der vorhandenen Klassen oder schreiben Sie Ihre eigene, nach ihrer Struktur. Hier ist eine Klasse, die für gepaarte Zeichen übereinstimmen würde:

class PairOf(Token):
    """Token for matching words composed of a pair
       of characters in a given set.
    """
    def __init__( self, chars ):
        super(PairOf,self).__init__()
        self.pair_chars = set(chars)

    def parseImpl( self, instring, loc, doActions=True ):
        if (loc < len(instring)-1 and 
           instring[loc] in self.pair_chars and
           instring[loc+1] == instring[loc]):
            return loc+2, instring[loc:loc+2]
        else:
            raise ParseException(instring, loc, "Not at a pair of characters")

Damit:

punc = r"~!@#$%^&*_-+=|\?/"
parser = OneOrMore(Word(alphas) | PairOf(punc))
print parser.parseString("Does ** this match @@@@ %% the parser?")

Gibt:

['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser']

(Beachten Sie die Auslassung der Hinter Single '?')

Andere Tipps

könnten Sie verwenden zipcode und foo getrennt, so dass Sie wissen, was man die Zeichenfolge entspricht.

zipresults = zipcode.parseString( t )
fooresults = foo.parseString( t )

Ich habe nicht das pyparsing Modul, sondern Regex muss eine Klasse sein, keine Funktion.

Was Sie tun können, ist Unterklasse von ihr und überschreiben Methoden nach Bedarf Verhalten anzupassen, dann stattdessen Ihre Unterklassen verwendet werden.

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