Давайте рассмотрим два эффективных способа работы с экранированными кавычками. Эти шаблоны не предназначены для того, чтобы быть краткими и эстетичными, но чтобы быть эффективными.
Эти способы используют различение первых символов, чтобы быстро найти кавычки в строке без затрат на чередование. (Идея в том, чтобы быстро отбросить символы, которые не являются кавычками, без проверки двух ветвей чередования.)
Содержимое между кавычками описывается с помощью развернутого цикла (вместо повторного чередования), чтобы быть более эффективным: [^"\\]*(?:\\.[^"\\]*)*
Очевидно, что для работы со строками, у которых нет сбалансированных кавычек, вы можете вместо этого использовать собственнические квантификаторы: [^"\\]*+(?:\\.[^"\\]*)*+
или обходной путь, чтобы эмулировать их, чтобы предотвратить слишком большой возврат. Вы также можете выбрать, чтобы цитируемая часть могла быть открывающей кавычкой до следующей (неэкранированной) кавычки или до конца строки. В этом случае нет необходимости использовать собственнические квантификаторы, нужно только сделать последнюю цитату необязательной.
Примечание: иногда кавычки не экранируются обратной косой чертой, а повторяются. В этом случае подшаблон содержимого выглядит так: [^"]*(?:""[^"]*)*
Шаблоны избегают использования группы захвата и обратной ссылки (я имею в виду что-то вроде (["']).....\1
) и используют простое чередование, но с ["']
в начале, как фактор.
Perl как:
["'](?:(?<=")[^"\\]*(?s:\\.[^"\\]*)*"|(?<=')[^'\\]*(?s:\\.[^'\\]*)*')
(обратите внимание, что (?s:...)
является синтаксическим сахаром для включения режима точек / однолинейных внутри группы без захвата. Если этот синтаксис не поддерживается, вы можете легко включить этот режим для всего шаблона или заменить точка с [\s\S]
)
(способ написания этого шаблона полностью «ручной» и не учитывает возможную внутреннюю оптимизацию движка)
Сценарий ECMA:
(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')
POSIX расширен:
"[^"\\]*(\\(.|\n)[^"\\]*)*"|'[^'\\]*(\\(.|\n)[^'\\]*)*'
или просто:
"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'