Регулярное выражение для строки в кавычках с кавычками - PullRequest
106 голосов
/ 30 октября 2008

Как получить подстроку " It's big \"problem " с помощью регулярного выражения?

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

Ответы [ 15 ]

0 голосов
/ 09 января 2018

Опция, которая раньше не затрагивалась:

  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#file-matchquotes-js

0 голосов
/ 21 сентября 2014

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

"(([^"\\]?(\\\\)?)|(\\")+)+"
0 голосов
/ 03 декабря 2013

Более расширенная версия https://stackoverflow.com/a/10786066/1794894

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

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

  1. Минимальная длина котировки 50
  2. Дополнительный тип котировок (открыть и закрыть )
0 голосов
/ 11 апреля 2013

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

\"((\\\")|[^\\])*\"
0 голосов
/ 30 октября 2008

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

...