Por ejemplo:

Si la cadena es un script "" normal ", la salida debe mostrar que la subcadena normal está entre comillas dobles, mientras que la subcadena script no lo está.

Para rastrear la subcadena entre comillas dobles desde una cadena, probé con la expresión regular:

r '"([^"] *) "'

Podemos usar el método split() para obtener la subcadena sin comillas dobles, pero estoy buscando un enfoque eficiente.

A continuación se muestra el código que probé: devuelve una lista de subcadenas con comillas dobles.

import re
def demo(text):      
    matches = re.findall(r'"([^"]*)"', text)
    return matches

a = demo('"normal" string "is here"')
print(a)

Además de encontrar subcadenas con comillas dobles, también estoy buscando subcadenas que no sean comillas dobles.

Por ejemplo, la salida de demo('"normal" string "is here"') debería ser:

Doble cita: ['normal', 'is here']

Sin comillas dobles: ['string']

0
Wasim Thabraze 1 mar. 2018 a las 17:23

4 respuestas

La mejor respuesta

Puede buscar cadenas entre comillas y comillas dobles en la misma expresión regular.

import re

def dequote(s):
    return re.findall(r'(?:"([^"]*)")|([^"]*)', s)

print(dequote('"normal" script'))
print(dequote('another "normal" script with "extra words in it"'))

La lista de aviso de tuplas devuelta contiene cadenas entre comillas y sin comillas. Las cadenas entre comillas están en el primer elemento de las tuplas, las cadenas sin comillas están en el segundo elemento.

Si desea separar las listas, es muy sencillo separarlas.

result = dequote('another "normal" script with "extra words in it"')

result_quoted = [t[0].strip() for t in result if t[0]]
result_unquoted = [t[1].strip() for t in result if t[1]]

print("double quoted: {}\nnot double quoted{}".format(
    result_quoted, result_unquoted))

La salida de todo el programa:

$ python x.py 
[('normal', ''), ('', ' script'), ('', '')]
[('', 'another '), ('normal', ''), ('', ' script with '), ('extra words in it', ''), ('', '')]
double quoted: ['normal', 'extra words in it']
not double quoted['another', 'script with']

Tenga en cuenta que implica que una solución basada en re irá más rápido que una basada en str.split(). No estoy convencido de eso. Considere estas dos soluciones:

def dequote_re(s):
    result = re.findall(r'(?:"([^"]*)")|([^"]*)', s)
    result_quoted = [t[0].strip() for t in result if t[0]]
    result_unquoted = [t[1].strip() for t in result if t[1]]
    return result_quoted, result_unquoted

def dequote_split(s):
    result = s.split('"')
    result_unquoted = [item.strip() for item in result[0::2] if item]
    result_quoted = [item.strip() for item in result[1::2] if item]
    return result_quoted, result_unquoted

Dan las mismas respuestas. Quizás deberías ejecutar timeit para encontrar cuál es más rápido para ti.

1
Robᵩ 1 mar. 2018 a las 14:50

Sé que split() es el más rápido y replace() es más rápido que la expresión regular, así que:

output = '"normal" script'.replace('"', '').split()

Salida: ['normal', 'script']

Tiempo de ejecución: 3.490e-05 seconds Usando regex obtienes tiempo entre 0.2e-04 y 0.3e-04

0
Srdjan M. 1 mar. 2018 a las 15:03

Con el regex módulo:

>>> import re, regex
>>> s='"normal" string "is here"'

>>> re.findall(r'"([^"]*)"', s)
['normal', 'is here']

# change \w to appropriate character class as needed
>>> regex.findall(r'"[^"]*"(*SKIP)(*F)|\w+', s)
['string']

# or a workaround, remove double quoted strings first
>>> re.findall(r'\w+', re.sub(r'"([^"]*)"', '', s))
['string']

Consulte Uso de (* SKIP) (* FAIL) para excluir coincidencias no deseadas Para una explicación detallada. En pocas palabras, agregue (*SKIP)(*F) a la expresión regular que desea excluir y, usando la alternancia, defina las que necesita

1
Sundeep 1 mar. 2018 a las 14:49

Si tiene una cadena bastante grande, puede usar la expresión regular para calcular las ocurrencias y lograr dividirla en pedazos más pequeños (depende de lo que espere obtener y de dónde).

Parece que tus subcadenas son palabras. Para las cadenas con comillas dobles o sin comillas dobles, puede dividirlas por subcadenas e ititerarlas como una lista.

La división entre comillas dobles o entre comillas dobles puede requerir la creación de dos listas.

Dividiendo por palabras, puede crear una sola lista de palabras y marcar la doble cita al generarla.

Ambos casos pueden costar casi lo mismo, dependiendo del tamaño de la cadena que obtenga.

Recomiendo usar el https://regexr.com e intente obtener la mayor cantidad posible de trozos de la cuerda que puede tratar .

Mi mejor.

0
David Allan Ribeiro 1 mar. 2018 a las 14:45