Python Regex Engine - "look-behind требует шаблона с фиксированной шириной". Ошибка

Я пытаюсь обрабатывать не совпадающие двойные кавычки внутри строки в формате CSV.

Если быть точным,

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

следует исправить как

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

Итак, в основном я пытаюсь сделать

замените все '' '

  • Не предшествует начало строки или запятая (и)
  • Не следует запятая или конец строки

с ' ""

Для этого я использую следующее регулярное выражение

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

Проблема заключается в том, что двигатели регулярных выражений Ruby (http://www.rubular.com/) могут анализировать регулярные выражения regex, python (https://pythex.org/, http://www.pyregex.com/), выполните следующую ошибку:

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

И с python 2.7.3 он бросает

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

Может ли кто-нибудь сказать мне, что здесь python vexes?

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

EDIT:

После ответа Тима я получил следующий вывод для многострочной строки

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

В конце каждой строки рядом с "этим" добавлены две двойные кавычки.

Итак, я сделал очень небольшое изменение в регулярном выражении, чтобы обработать новую строку.

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

Но это дает выход

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

В последнем "единственном" есть две двойные кавычки.

Но мне интересно, почему символ $$ конца строки не будет идентифицировать, что строка закончилась.

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

Последний ответ

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

Ответы

Ответ 1

Утверждения Python lookbehind должны быть фиксированной шириной, но вы можете попробовать следующее:

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

Объяснение:

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

Ответ 2

Python lookbehind действительно нуждается в фиксированной ширине, и когда у вас есть чередование в шаблоне lookbehind различной длины, есть несколько способов справиться с этой ситуацией:

  • Перепишите шаблон так, чтобы вам не пришлось использовать чередование (например, Tim выше ответ, используя границу слова, или вы также можете использовать точный эквивалент (?<=[^,])"(?!,|$) вашего текущего шаблона, для которого требуется char, кроме запятой перед двойной кавычкой или общим шаблоном для сопоставления слов, заключенных в пробелы, (?<=\s|^)\w+(?=\s|$), можно записать как (?<!\S)\w+(?!\S)) или
  • Разделите lookbehinds:
    • Положительные lookbehind должны чередоваться в группе (например, (?<=a|bc) следует переписать как (?:(?<=a)|(?<=bc)))
    • Отрицательные lookbehind могут быть просто объединены (например, (?<!^|,)"(?!,|$) должен выглядеть как (?<!^)(?<!,)"(?!,|$)).