2011-06-07 8 views
9

Me han dado algunas condiciones para trabajar. Cada uno representa un conjunto de datos y consta del nombre del conjunto de datos y las estadísticas asociadas. Todos ellos tienen la siguiente forma:Python Regex para analizar Cadena y devolver Tuple

s= "| 'TOMATOES_PICKED'         |  914 |  1397 |" 

Estoy tratando de implementar una función que va a analizar la cadena y devolver el nombre del conjunto de datos, el primer número y el segundo número. Hay muchas de estas cadenas y cada una tiene un nombre diferente y estadísticas asociadas, así que he pensado que la mejor manera de hacerlo es con expresiones regulares. Esto es lo que tengo hasta ahora:

def extract_data2(s): 
    import re 
    name=re.search('\'(.*?)\'',s).group(1) 
    n1=re.search('\|(.*)\|',s) 
    return(name,n1,) 

Así que he hecho un poco de lectura sobre las expresiones regulares y descubierto la manera de devolver el nombre. Para cada una de las cadenas con las que estoy trabajando, el nombre del conjunto de datos está delimitado por '', así es como encontré el nombre. Esa parte funciona bien. Mi problema es obtener los números. Lo que estoy pensando ahora es intentar hacer coincidir un patrón que está precedido por una barra vertical ('|'), luego cualquier cosa (que es por lo que utilicé. *), Y seguido por otra barra vertical para tratar de obtener el primer número. ¿Alguien sabe cómo puedo hacer esto en Python? Lo que probé en el código anterior para el primer número devuelve básicamente toda la cadena como mi salida, mientras que quiero obtener solo el número. -Estoy muy nuevo en la programación, así que me disculpo si esta pregunta parece rudimentaria, pero he estado leyendo y buscando bastante diligentemente las respuestas que están cerca de mi caso sin suerte. Agradezco cualquier ayuda. La idea es que va a ser capaz de:

return(name,n1,n2) 

de modo que cuando el usuario introduce una cadena, sólo se puede analizar la secuencia y devolver la información importante. Me he dado cuenta en mis intentos de obtener los números hasta ahora que devolverá el número como una cadena. ¿Hay alguna forma de devolver n1 o n2 como solo un número? Tenga en cuenta que para algunas de las cadenas n1 y n2 podrían ser enteros o tener un decimal.

+4

Este tipo de cadenas con campos bien definidos a menudo son más rápidas y fáciles de analizar utilizando solo la división de cadenas, picado, etc., p. Ej. '[str.strip for ss in" | ".split (s)]' te ayudará a comenzar. – Keith

Respuesta

17

me gustaría utilizar una sola expresión regular para que coincida con la línea completa, con las partes que quiero en grupos nombrados ((?P<name>exampl*e)).

import re 
def extract_data2(s): 
    pattern = re.compile(r"""\|\s*     # opening bar and whitespace 
          '(?P<name>.*?)'  # quoted name 
          \s*\|\s*(?P<n1>.*?) # whitespace, next bar, n1 
          \s*\|\s*(?P<n2>.*?) # whitespace, next bar, n2 
          \s*\|""", re.VERBOSE) 
    match = pattern.match(s) 

    name = match.group("name") 
    n1 = float(match.group("n1")) 
    n2 = float(match.group("n2")) 

    return (name, n1, n2) 

Para convertir n1 y n2 de cadenas en números, utilizo la función float. (Si fueran sólo enteros, usaría la función int.)

he utilizado la bandera re.VERBOSE y varias líneas prima cuerdas (r"""...""") para hacer la expresión regular más fácil de leer.

+0

Esto funcionó maravillosamente. Me gusta lo que algunos de los otros carteles decían sobre la división, y puedo ver muchos usos para ello. Pero lo había intentado antes y solo podía devolver los números como cadenas. Muchas gracias por su aporte. ¡Fue muy informativo! –

1

No estoy seguro de que he entendido, pero tratar esto correctamente:

import re 

print re.findall(r'\b\w+\b', yourtext) 
2

El uso de expresiones regulares:

#! /usr/bin/env python 

import re 

tests = [ 
"| 'TOMATOES_PICKED'         |  914 |  1397 |", 
"| 'TOMATOES_FLICKED'         |  32914 |  1123 |", 
"| 'TOMATOES_RIGGED'         |  14 |  1343 |", 
"| 'TOMATOES_PICKELED'        |   4 |   23 |"] 

def parse (s): 
    mo = re.match ("\\|\s*'([^']*)'\s*\\|\s*(\d*)\s*\\|\s*(\d*)\s*\\|", s) 
    if mo: return mo.groups() 

for test in tests: print parse (test) 
3

Intente utilizar dividida.

s= "| 'TOMATOES_PICKED'         |  914 |  1397 |" 
print map(lambda x:x.strip("' "),s.split('|'))[1:-1] 
  • Dividir: transformar su cadena en una lista de cuerda función
  • lambda: elimina los espacios y '
  • Selector: tomar las piezas solamente esperados
0

Con pyparsing, puede tener el analizador crea una estructura similar a un dictado para usted, utilizando los primeros valores de columna como las claves, y los valores posteriores como una matriz de valores para esa clave:

>>> from pyparsing import * 
>>> s = "| 'TOMATOES_PICKED'         |  914 |  1397 |" 
>>> VERT = Suppress('|') 
>>> title = quotedString.setParseAction(removeQuotes) 
>>> integer = Word(nums).setParseAction(lambda tokens:int(tokens[0])) 
>>> entry = Group(VERT + title + VERT + integer + VERT + integer + VERT) 
>>> entries = Dict(OneOrMore(entry)) 
>>> data = entries.parseString(s) 
>>> data.keys() 
['TOMATOES_PICKED'] 
>>> data['TOMATOES_PICKED'] 
([914, 1397], {}) 
>>> data['TOMATOES_PICKED'].asList() 
[914, 1397] 
>>> data['TOMATOES_PICKED'][0] 
914 
>>> data['TOMATOES_PICKED'][1] 
1397 

Esto ya comprende entradas múltiples, por lo que puede simplemente pasarle una cadena multilínea única que contiene todos sus valores de datos, y se construirá una estructura de datos con clave única para usted. (Procesar este tipo de datos tabulares delimitados por tuberías fue una de las primeras aplicaciones que tuve para pyparsing.)

1

Tendría que estar de acuerdo con los otros carteles que decían usar el método split() en sus cadenas. Si su cadena dada es,

>> s = "| 'TOMATOES_PICKED'       |  914 |  1397 |" 

Sólo dividir la cadena y listo, ahora tiene una lista con el nombre en la segunda posición, y los dos valores en las siguientes entradas, es decir

>> s_new = s.split() 
>> s_new 
['|', "'TOMATOES_PICKED'", '|', '914', '|', '1397', '|'] 

Por supuesto que también tiene el "|" personaje pero eso parece ser consistente en su conjunto de datos, por lo que no es un gran problema tratar con él. Sólo ingoralos.

Cuestiones relacionadas