2008-10-24 27 views
7

que tienen una cadena que es así:división de cadenas en Python

esto es [Prueba de soporte] "y cita a prueba"

Estoy tratando de escribir algo en Python para dividirlo por el espacio mientras se ignoran los espacios entre corchetes cuadrados y comillas. El resultado que estoy buscando es:

[ 'esto', 'es', 'prueba de soporte' 'y cita a prueba']

+1

¿Anidan los soportes? ¿Puede haber corchetes sin igual entre comillas? ¿Qué hay de las comillas o corchetes sin igual? ¿Cuál es el resultado correcto para lo siguiente: [[paréntesis anidados] prueba] "sujetador [entre comillas" "ket] entre comillas" [cita "entre paréntesis]"] –

Respuesta

8

Aquí es una solución simplista que funciona con su entrada de prueba:

import re 
re.findall('\[[^\]]*\]|\"[^\"]*\"|\S+',s) 

Esto devolverá cualquier código que coincide con cualquiera de los dos

  • un soporte abierto seguido de cero o más caracteres no cerca del soporte seguido de un corchete de cierre,
  • una doble comilla seguida de cero o más caracteres no cita seguido de una cita,
  • cualquier grupo de caracteres no está en blanco

Esto funciona con su ejemplo, pero podría fallar por muchas cadenas del mundo real puedes encontrarte. Por ejemplo, no dijo lo que esperaba con corchetes o citas desbalanceadas, o cómo desea que funcionen las comillas simples o los caracteres de escape. Para casos simples, sin embargo, lo anterior podría ser lo suficientemente bueno.

+0

Esto deja las comillas y los corchetes. Que no es precisamente lo que se pidió. –

1

Aquí hay un analizador simplista (probado en su entrada de ejemplo) que presenta el patrón de diseño de estado.

En el mundo real, es probable que desee construir un analizador real usando algo como PLY.

class SimpleParser(object): 

    def __init__(self): 
     self.mode = None 
     self.result = None 

    def parse(self, text): 
     self.initial_mode() 
     self.result = [] 
     for word in text.split(' '): 
      self.mode.handle_word(word) 
     return self.result 

    def initial_mode(self): 
     self.mode = InitialMode(self) 

    def bracket_mode(self): 
     self.mode = BracketMode(self) 

    def quote_mode(self): 
     self.mode = QuoteMode(self) 


class InitialMode(object): 

    def __init__(self, parser): 
     self.parser = parser 

    def handle_word(self, word): 
     if word.startswith('['): 
      self.parser.bracket_mode() 
      self.parser.mode.handle_word(word[1:]) 
     elif word.startswith('"'): 
      self.parser.quote_mode() 
      self.parser.mode.handle_word(word[1:]) 
     else: 
      self.parser.result.append(word) 


class BlockMode(object): 

    end_marker = None 

    def __init__(self, parser): 
     self.parser = parser 
     self.result = [] 

    def handle_word(self, word): 
     if word.endswith(self.end_marker): 
      self.result.append(word[:-1]) 
      self.parser.result.append(' '.join(self.result)) 
      self.parser.initial_mode() 
     else: 
      self.result.append(word) 

class BracketMode(BlockMode): 
    end_marker = ']' 

class QuoteMode(BlockMode): 
    end_marker = '"' 
-2

Funciona solo para presupuestos.

rrr = [] 
qqq = s.split('\"') 
[ rrr.extend(qqq[x].split(), [ qqq[x] ])[ x%2]) for x in range(len(qqq))] 
print rrr 
0

Aquí es un enfoque más de procedimiento:

#!/usr/bin/env python 

a = 'this is [bracket test] "and quotes test "' 

words = a.split() 
wordlist = [] 

while True: 
    try: 
     word = words.pop(0) 
    except IndexError: 
     break 
    if word[0] in '"[': 
     buildlist = [word[1:]] 
     while True: 
      try: 
       word = words.pop(0) 
      except IndexError: 
       break 
      if word[-1] in '"]': 
       buildlist.append(word[:-1]) 
       break 
      buildlist.append(word) 
     wordlist.append(' '.join(buildlist)) 
    else: 
     wordlist.append(word) 

print wordlist 
5

Para completar Bryan puesto y coincidir exactamente con la respuesta:

>>> import re 
>>> txt = 'this is [bracket test] "and quotes test "' 
>>> [x[1:-1] if x[0] in '["' else x for x in re.findall('\[[^\]]*\]|\"[^\"]*\"|\S+', txt)] 
['this', 'is', 'bracket test', 'and quotes test '] 

no entienden mal toda la sintaxis utilizada: No se trata de varios declaraciones en una sola línea pero una sola declaración funcional (más a prueba de errores).

0

Bueno, he encontrado este problema bastantes veces, lo que me llevó a escribir mi propio sistema para analizar cualquier tipo de sintaxis.

El resultado de esto se puede encontrar here; tenga en cuenta que esto puede ser excesivo, y le proporcionará algo que le permite analizar enunciados con corchetes y paréntesis, comillas simples o dobles, tan anidados como desee. Por ejemplo, se podría analizar algo como esto (ejemplo escrito en Common Lisp):

(defun hello_world (&optional (text "Hello, World!")) 
    (format t text)) 

Puede utilizar el agrupamiento, soportes (cuadrados) y paréntesis (redondos), de una y cadenas entre comillas dobles, y es muy extensible.

La idea es básicamente una implementación configurable de una máquina de estados finitos que construye un árbol de sintaxis abstracto carácter por carácter. Te recomiendo que mires el código fuente (ver enlace arriba), para que puedas hacerte una idea de cómo hacerlo. Es capaz a través de expresiones regulares, pero intente escribir un sistema utilizando RE y luego tratar de extenderlo (o incluso entenderlo) más tarde.

Cuestiones relacionadas