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.
"(.*?[^\\])??((\\\\)+)?+"
Объяснение:
- Каждая строка в кавычках начинается с Char:
"
; - Может содержать любое количество любых символов:
.*?
{Ленивый матч}; заканчивая не экранированным символом[^\\]
; - Оператор (2) является Lazy(!) Необязательным, поскольку строка может быть пустой (""). Так:
(.*?[^\\])??
- Наконец, каждая строка в кавычках заканчивается символом Char (
"
), но ему может предшествовать четное число пар escape-знаков(\\\\)+
; и это жадный (!) необязательно:((\\\\)+)?+
{Жадное совпадение}, потому что строка может быть пустой или без конечных пар!
Опция, которая не была затронута ранее:
- Переверните строку.
- Выполните сопоставление с обращенной строкой.
- Переверните совпавшие строки.
Это дает дополнительный бонус, заключающийся в том, что он может правильно сопоставлять экранированные открытые теги.
Допустим, у вас была следующая строка; 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), совпадающую с первой группой ("или").
Если поиск производится с самого начала, может, это сработает?
\"((\\\")|[^\\])*\"
Нужно помнить, что регулярные выражения не являются серебряной пулей для всего подряд. Некоторые вещи проще сделать с помощью курсора и линейного, ручного поиска. КЛЛ сделал бы довольно просто, но реализации КЛЛ не так много (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,}(\\.[^“\\]*)*”/
Эта версия также содержит
- Минимальная длина цитаты 50
- Дополнительный тип цитат (открытый
“
и закрыть”
)
(?<="|')(?:[^"\\]|\\.)*(?="|')
" Это большая проблема " результат матча: Это большая проблема
("|')(?:[^"\\]|\\.)*("|')
" Это большая \"проблема " результат матча: " Это большая \"проблема "
Перепутались в регулярном выражении и закончили этим регулярным выражением: (Не спрашивайте меня, как это работает, я едва понимаю, даже если я написал это, смеется)
"(([^"\\]?(\\\\)?)|(\\")+)+"