Python Regex Engine – Error de “look-behind requiere patrón de ancho fijo”

Estoy tratando de manejar las comillas dobles no coincidentes dentro de una cadena en el formato CSV.

Para ser preciso,

"It "does "not "make "sense", Well, "Does "it" 

debe ser corregido como

 "It" "does" "not" "make" "sense", Well, "Does" "it" 

Así que básicamente lo que estoy tratando de hacer es

Reemplace todos los ” ‘

  1. No precedido por un principio de línea o una coma (y)
  2. No seguido por una coma o un final de línea

con ‘ ” ” ‘

Para eso uso el regex de abajo.

 (?<!^|,)"(?!,|$) 

El problema es que los motores de expresiones regulares de Ruby ( http://www.rubular.com/ ) son capaces de analizar las expresiones regulares, los motores de expresiones regulares de Python ( https://pythex.org/ , http://www.pyregex.com/ ) lanzar el siguiente error

 Invalid regular expression: look-behind requires fixed-width pattern 

Y con el python 2.7.3 lanza.

 sre_constants.error: look-behind requires fixed-width pattern 

¿Alguien puede decirme qué vexes python aquí?

================================================== ================================

EDITAR:

Siguiendo la respuesta de Tim, obtuve la siguiente salida para una cadena de varias líneas

 >>> str = """ "It "does "not "make "sense", Well, "Does "it" ... "It "does "not "make "sense", Well, "Does "it" ... "It "does "not "make "sense", Well, "Does "it" ... "It "does "not "make "sense", Well, "Does "it" """ >>> re.sub(r'\b\s*"(?!,|$)', '" "', str) ' "It" "does" "not" "make" "sense", Well, "Does" "it" "\n"It" "does" "not" "make" "sense", Well, "Does" "it" "\n"It" "does" "not" "make" "sense", Well, "Does" "it" "\n"It" "does" "not" "make" "sense", Well, "Does" "it" " ' 

Al final de cada línea, junto a ‘it’ se agregaron dos comillas dobles.

Así que hice un cambio muy pequeño a la expresión regular para manejar una nueva línea.

 re.sub(r'\b\s*"(?!,|$)', '" "', str,flags=re.MULTILINE) 

Pero esto da la salida.

 >>> re.sub(r'\b\s*"(?!,|$)', '" "', str,flags=re.MULTILINE) ' "It" "does" "not" "make" "sense", Well, "Does" "it"\n... "It" "does" "not" "make" "sense", Well, "Does" "it"\n... "It" "does" "not" "make" "sense", Well, "Does" "it"\n... "It" "does" "not" "make" "sense", Well, "Does" "it" " ' 

El último ‘it’ solo tiene dos comillas dobles.

Pero me pregunto por qué el carácter de final de línea ‘$’ no identificará que la línea haya terminado.

================================================== ================================

La respuesta final es

 re.sub(r'\b\s*"(?!,|[ \t]*$)', '" "', str,flags=re.MULTILINE) 

Las aserciones de Python lookbehind deben ser de ancho fijo, pero puedes intentar esto:

 >>> s = '"It "does "not "make "sense", Well, "Does "it"' >>> re.sub(r'\b\s*"(?!,|$)', '" "', s) '"It" "does" "not" "make" "sense", Well, "Does" "it"' 

Explicación:

 \b # Start the match at the end of a "word" \s* # Match optional whitespace " # Match a quote (?!,|$) # unless it's followed by a comma or end of string 

Las miras de Python realmente necesitan ser de ancho fijo, y cuando tienes alternaciones en un patrón de mirada que está detrás de una longitud diferente, hay varias formas de manejar esta situación:

  • Vuelva a escribir el patrón para que no tenga que usar la alternancia (por ejemplo, la respuesta anterior de Tim usando un límite de palabra, o también podría usar un equivalente exacto (?<=[^,])"(?!,|$) su stream El patrón que requiere un carácter distinto de una coma antes de la comilla doble, o un patrón común para hacer coincidir las palabras entre espacios en blanco, (?<=\s|^)\w+(?=\s|$) , se puede escribir como (? ), o
  • Dividir la mirada detrás de
    • Las miradas positivas deben alternarse en un grupo (por ejemplo, (?<=a|bc) deben reescribir como (?:(?<=a)|(?<=bc)) )
    • Las miradas negativas pueden estar concatenadas (por ejemplo, (? Debe verse como (? ).