Pregunta

Este código funciona:

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

Estoy atascado en dos cuestiones:

1 - Cómo utilizar una función personalizada para analizar una muestra. Por ejemplo, si quería usar algo de lógica personalizada en lugar de una expresión regular para determinar si un número es un código postal. En lugar de:

zipcode = Regex( zipRE )

quizá:

zipcode = MyFunc()

2 - ¿Cómo se determina lo que analiza una cadena A. "80001" un análisis sintáctico de "código postal" pero ¿cómo puedo determinar esto utilizando pyparsing? No estoy analizar una cadena por su contenido sino simplemente para determinar qué tipo de consulta que es.

¿Fue útil?

Solución

Su segunda pregunta es fácil, así que voy a responder a eso en primer lugar. Cambio de buscar resultados para asignar nombres a las diferentes expresiones:

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

Ahora se puede llamar getName () en el resultado devuelto:

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

El dar:

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

Si va a utilizar fooness o zipness del resultado de llamar a otra función, entonces se podría hacer esto en tiempo de análisis adjuntando una acción de análisis a sus foo y código postal expresiones:

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

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

Ahora da:

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

En su primera pregunta, no lo sé exactamente qué tipo de función que quiere decir. Pyparsing ofrece muchas más clases de análisis que sólo expresiones regulares (como Word, Palabra clave, literal, CaselessLiteral), y estás componiendo un analizador combinándolos con '+', '|', '^', '~', '@' y '*' operadores. Por ejemplo, si desea analizar para un número de seguridad social de Estados Unidos, pero no utilizar una expresión regular, se puede usar:

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

Palabra partidos de "palabras" contiguos formados por los caracteres dados en su constructor, Combinar concatena las fichas coincidentes en una sola ficha.

Si usted quiere analizar para obtener una lista potencial de tales números, delimitado por '/' s, utilice:

delimitedList(ssn, '/')

o si había entre 1 y 3 tales números, sin delimters, utilice:

ssn * (1,3)

Y cualquier expresión puede tener resultados nombres o analizar las acciones unidos a ellos, para enriquecer aún más los resultados analizados, o la funcionalidad durante el análisis. Incluso se puede construir analizadores recursivos, tales como listas anidadas de paréntesis, expresiones aritméticas, etc, utilizando la clase Adelante.

Mi intención al escribir pyparsing era que esta composición de programas de análisis a partir de bloques de construcción básicos sería la forma principal para la creación de un programa de análisis. Fue sólo en una versión posterior que añadí expresión regular como (lo que, aunque era) la válvula último escape - si la gente no podía construir su programa de análisis, que podrían caer de nuevo en formato de expresiones regulares, lo que sin duda ha demostrado su poder sobre el tiempo.

O, como otro cartel sugiere, se puede abrir la fuente pyparsing, y la subclase una de las clases existentes, o escribir su propia, a raíz de su estructura. Aquí es una clase que se correspondería con los caracteres emparejados:

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")

Así que:

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

Da:

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

(Tenga en cuenta la omisión del arrastre sencillo '?')

Otros consejos

Se puede usar código postal y comida por separado, de modo que usted sabe que uno de los partidos de cuerda.

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

No tengo el módulo pyparsing, pero Regex debe ser una clase, no una función.

Lo que puede hacer es subclase de ella y métodos de anulación según sea necesario para personalizar el comportamiento, a continuación, utilizar sus subclases en su lugar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top