Regex for quoted string with escaping quotes

How do I get the substring " It's big \"problem " используя регулярное выражение?

s = ' function(){  return " It\'s big \"problem  ";  }';     

17 ответов

/"(?:[^"\\]|\\.)*"/

Работает в Regex Coach и PCRE Workbench.

Пример теста в JavaScript:

    var s = ' function(){ return " Is big \\"problem\\", \\no? "; }';
    var m = s.match(/"(?:[^"\\]|\\.)*"/);
    if (m != null)
        alert(m);

Это из nanorc.sample, доступного во многих дистрибутивах Linux. Используется для подсветки синтаксиса строк в стиле C

\"(\\.|[^\"])*\"

Ответ предоставлен ePharaoh.

/"([^"\\]*(\\.[^"\\]*)*)"/

Чтобы вышеприведенное применимо к строкам с одинарными или двойными кавычками, используйте

/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/

Большинство решений, представленных здесь, используют альтернативные пути повторения, т.е. (A|B)*.

Вы можете столкнуться с переполнением стека на больших входах, так как некоторые компиляторы шаблонов реализуют это с помощью рекурсии.

Например, Java: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993

Что-то вроде этого:"(?:[^"\\]*(?:\\.)?)*"или тот, который предоставлен Гаем Бедфордом, уменьшит количество шагов анализа, избегая большинства переполнений стека.

/(["\']).*?(?<!\\)(\\\\)*\1/is

должен работать с любой строкой в ​​кавычках

"(?:\\"|.)*?"

Чередование \" и . проходит через кавычки, в то время как ленивый квантификатор *? гарантирует, что вы не пройдете конец строки в кавычках. Работает с классами.NET Framework RE

/"(?:[^"\\]++|\\.)*+"/

Взяты прямо из man perlre в системе Linux с установленным Perl 5.22.0. В качестве оптимизации это регулярное выражение использует "притягательную" форму обоих + а также * для предотвращения возврата, так как заранее известно, что строка без закрывающей кавычки ни в коем случае не будет соответствовать.

Этот работает отлично на PCRE и не падает со Stackru.

"(.*?[^\\])??((\\\\)+)?+"

Объяснение:

  1. Каждая строка в кавычках начинается с Char: ";
  2. Может содержать любое количество любых символов: .*? {Ленивый матч}; заканчивая не экранированным символом [^\\];
  3. Оператор (2) является Lazy(!) Необязательным, поскольку строка может быть пустой (""). Так: (.*?[^\\])??
  4. Наконец, каждая строка в кавычках заканчивается символом Char ("), но ему может предшествовать четное число пар escape-знаков (\\\\)+; и это жадный (!) необязательно: ((\\\\)+)?+ {Жадное совпадение}, потому что строка может быть пустой или без конечных пар!

Опция, которая не была затронута ранее:

  1. Переверните строку.
  2. Выполните сопоставление с обращенной строкой.
  3. Переверните совпавшие строки.

Это дает дополнительный бонус, заключающийся в том, что он может правильно сопоставлять экранированные открытые теги.

Допустим, у вас была следующая строка; String \"this "should" NOT match\" and "this \"should\" match"Вот, \"this "should" NOT match\" не должны совпадать и "should" должно быть. Более того this \"should\" match должны быть сопоставлены и \"should\" не следует.

Сначала пример.

// The input string.
const myString = 'String \\"this "should" NOT match\\" and "this \\"should\\" match"';

// The RegExp.
const regExp = new RegExp(
    // Match close
    '([\'"])(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))' +
    '((?:' +
        // Match escaped close quote
        '(?:\\1(?=(?:[\\\\]{2})*[\\\\](?![\\\\])))|' +
        // Match everything thats not the close quote
        '(?:(?!\\1).)' +
    '){0,})' +
    // Match open
    '(\\1)(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))',
    'g'
);

// Reverse the matched strings.
matches = myString
    // Reverse the string.
    .split('').reverse().join('')
    // '"hctam "\dluohs"\ siht" dna "\hctam TON "dluohs" siht"\ gnirtS'

    // Match the quoted
    .match(regExp)
    // ['"hctam "\dluohs"\ siht"', '"dluohs"']

    // Reverse the matches
    .map(x => x.split('').reverse().join(''))
    // ['"this \"should\" match"', '"should"']

    // Re order the matches
    .reverse();
    // ['"should"', '"this \"should\" match"']

Хорошо, теперь, чтобы объяснить RegExp. Это регулярное выражение можно легко разбить на три части. Следующее:

# Part 1
(['"])         # Match a closing quotation mark " or '
(?!            # As long as it's not followed by
  (?:[\\]{2})* # A pair of escape characters
  [\\]         # and a single escape
  (?![\\])     # As long as that's not followed by an escape
)
# Part 2
((?:          # Match inside the quotes
(?:           # Match option 1:
  \1          # Match the closing quote
  (?=         # As long as it's followed by
    (?:\\\\)* # A pair of escape characters
    \\        # 
    (?![\\])  # As long as that's not followed by an escape
  )           # and a single escape
)|            # OR
(?:           # Match option 2:
  (?!\1).     # Any character that isn't the closing quote
)
)*)           # Match the group 0 or more times
# Part 3
(\1)           # Match an open quotation mark that is the same as the closing one
(?!            # As long as it's not followed by
  (?:[\\]{2})* # A pair of escape characters
  [\\]         # and a single escape
  (?![\\])     # As long as that's not followed by an escape
)

Это, вероятно, намного яснее в форме изображения: генерируется с помощью Jex's Regulex.

Изображение на github (визуализатор регулярных выражений JavaScript). Извините, у меня недостаточно высокая репутация, чтобы включать изображения, поэтому пока это просто ссылка.

Вот пример функции, использующей эту концепцию, которая немного более продвинута: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc

Вот тот, который работает с обоими "и", и вы легко добавляете другие в начале.

("|") (:\\\1|[^\1])? * \ 1

он использует точную обратную ссылку (\ 1), совпадающую с первой группой ("или").

http://www.regular-expressions.info/backref.html

Если поиск производится с самого начала, может, это сработает?

\"((\\\")|[^\\])*\"

Нужно помнить, что регулярные выражения не являются серебряной пулей для всего подряд. Некоторые вещи проще сделать с помощью курсора и линейного, ручного поиска. КЛЛ сделал бы довольно просто, но реализации КЛЛ не так много (afaik).

Я столкнулся с подобной проблемой при попытке удалить строки в кавычках, которые могут помешать синтаксическому анализу некоторых файлов.

Я получил двухэтапное решение, которое превосходит любое сложное регулярное выражение, которое вы можете придумать:

 line = line.replace("\\\"","\'"); // Replace escaped quotes with something easier to handle
 line = line.replaceAll("\"([^\"]*)\"","\"x\""); // Simple is beautiful

Легче читать и, вероятно, более эффективно.

Если ваша IDE - это IntelliJ Idea, вы можете забыть обо всех этих головных болях и сохранить свое регулярное выражение в переменной String, и когда вы скопируете и вставите его в двойные кавычки, оно автоматически изменится на приемлемый формат регулярного выражения.

пример на Java:

String s = "\"en_usa\":[^\\,\\}]+";

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

Более расширенная версия /questions/550445/regex-for-quoted-string-with-escaping-quotes/550449#550449

/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/   

Эта версия также содержит

  1. Минимальная длина цитаты 50
  2. Дополнительный тип цитат (открытый и закрыть )
      (?<="|')(?:[^"\\]|\\.)*(?="|')

" Это большая проблема " результат матча: Это большая проблема

      ("|')(?:[^"\\]|\\.)*("|')

" Это большая \"проблема " результат матча: " Это большая \"проблема "

Перепутались в регулярном выражении и закончили этим регулярным выражением: (Не спрашивайте меня, как это работает, я едва понимаю, даже если я написал это, смеется)

"(([^"\\]?(\\\\)?)|(\\")+)+"
Другие вопросы по тегам