Как получить подстроку " It's big \"problem " с помощью регулярного выражения?
s = ' function(){ return " It\'s big \"problem "; }';
Дубликат: PHP: регулярное выражение для игнорирования экранированных кавычек внутри кавычек
Собственно, глядя на даты, я вижу, что второй вопрос является дубликатом этого. В любом случае, обязательно проверьте мой ответ.
@ridgerunner: Я голосую за то, чтобы закрыть это, как вы предложили. Верно, что другой вопрос более свежий, но он также намного лучше (в основном благодаря вашему ответу).





/(["\']).*?(?<!\\)(\\\\)*\1/is
должен работать с любой строкой в кавычках
Красиво, но слишком гибко для запроса (будет соответствовать одинарным кавычкам ...). И может быть упрощен до /".*?(?<!\)"/, если я что-то не пропущу. Да, и некоторые языки (например, JavaScript), увы, не понимают выражения отрицательного просмотра назад.
@PhiLho, простое использование одного (? <! \\) приведет к сбою при экранировании обратной косой черты в конце строки. Однако верно в отношении ретроспективного анализа в JavaScript.
Следует помнить, что регулярные выражения - не панацея для всего строкового. Некоторые вещи проще сделать с помощью курсора и линейного ручного поиска. CFL справился бы с этой задачей довольно тривиально, но реализаций CFL не так много (afaik).
Это верно, но эта проблема вполне доступна для регулярных выражений, и существует множество их реализаций.
/"(?:[^"\\]|\\.)*"/
Работает в Regex Coach и PCRE Workbench.
Пример теста на JavaScript:
var s = ' function(){ return " Is big \\"problem\\", \\no? "; }';
var m = s.match(/"(?:[^"\\]|\\.)*"/);
if (m != null)
alert(m);Имеет смысл. Обычный английский: две кавычки, окружающие ноль или более «любого символа, кроме кавычек или обратной косой черты» или «обратной косой черты, за которой следует любой символ». Не могу поверить, что не думал об этом ...
Я сам отвечу. =) (?:...) - это пассивная или не захватывающая группа. Это означает, что на него нельзя ссылаться позже.
после долгих поисков и тестов это настоящее и единственное решение, которое я нашел для этой распространенной проблемы. Спасибо!
Спасибо за это. Я также хотел сопоставить одинарные кавычки, поэтому в итоге я адаптировал его к этому: /(["'])(?:[^\1\\]|\\.)*?\1/
С var s = ' my \\"new\\" string and \"this should be matched\"'; этот подход приведет к неожиданным результатам.
@ WiktorStribiżew Ваша строка не соответствует описанию: строка, содержащая часть в двойных кавычках, которая может содержать экранированные двойные кавычки. Не уверен, чего вы ожидаете ...
Для тех, кто заинтересован, размещение "\\." в первую очередь дает лучшую производительность. Я предполагаю, что это потому, что это сначала делает дополнительный поиск обратной косой черты в "[^"\\]" избыточным. Глядя на другие ответы, такие как приведенный ниже Даррелл, дает более производительное регулярное выражение (и оно включено во многие дистрибутивы Linux в соответствии с ответом). Так что для производительности используйте \"(\\.|[^\"])*\". Расчет времени в Python 3.7 дал 1,375 миллисекунда против 1,55 миллисекунды.
@ nr5 Я не знаю Свифта. Возможно, вам нужно удвоить обратную косую черту все, если у него нет специального синтаксиса для регулярных выражений. Обычно мы делаем это в C, Java и т. д., Потому что RE - это просто строки. (Предполагая, что вы говорите о синтаксической ошибке, а не об ошибке времени выполнения, это не ясно, вы даже не даете сообщение об ошибке ...)
Перевод: совпадение цитаты, совпадение одного символа, кроме кавычек или обратной косой черты, ИЛИ сопоставление 2 символов, если первый является обратной косой чертой, совпадение предыдущей группы ноль или более раз, совпадение цитаты.
Это происходит из nanorc.sample, доступного во многих дистрибутивах Linux. Используется для подсветки синтаксиса строк в стиле C.
\"(\\.|[^\"])*\"
С var s = ' my \\"new\\" string and \"this should be matched\"'; этот подход приведет к неожиданным результатам.
c.nanorc был первым местом, куда я пошел. Не удалось заставить его работать как часть строкового литерала C до тех пор, пока он не экранировал все, как этот " \"(\\\\.|[^\\\"])*\" "
Это работает с функциями egrep и re_comp / re_exec из libc.
"(?:\\"|.)*?"
При чередовании \" и . пропускаются экранированные кавычки, в то время как ленивый квантификатор *? гарантирует, что вы не пройдете за конец строки в кавычках. Работает с классами .NET Framework RE
Но не получается с "\\"
var s = ' my \\"new\\" string and \"this should be matched\"';/"(?:(?:\\"|[^"])*)"/g это должно исправить
Как сообщает ePharaoh, ответ:
/"([^"\\]*(\\.[^"\\]*)*)"/
Чтобы вышеуказанное применимо к строкам в одинарных или двойных кавычках, используйте
/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
Это единственный набор, который у меня работал с одной большой строкой в кавычках размером 1,5 КБ, содержащей 99 экранирований. Все остальные выражения на этой странице в моем текстовом редакторе прерывались с ошибкой переполнения. Хотя большинство из них работает в браузере, о чем-то нужно помнить. Рабочий пример: jsfiddle.net/aow20y0L
См. Ответ @ MarcAndrePoulin ниже для объяснения.
Если искать с самого начала, может это сработает?
\"((\\\")|[^\\])*\"
Более обширная версия https://stackoverflow.com/a/10786066/1794894
/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/
Эта версия также содержит
“ и закрыть ”)Возился с регулярное выражение и закончил с этим регулярным выражением: (Не спрашивайте меня, как это работает, я почти не понимаю, даже хотя я написал это lol)
"(([^"\\]?(\\\\)?)|(\\")+)+"
В большинстве представленных здесь решений используются альтернативные пути повторения, например (A | B) *.
Вы можете столкнуться с переполнением стека при больших входных данных, поскольку некоторые компиляторы шаблонов реализуют это с помощью рекурсии.
Например, Java: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993
Что-то вроде этого:
"(?:[^"\\]*(?:\\.)?)*" или тот, который предоставлен Гаем Бедфордом, уменьшит количество шагов синтаксического анализа, избегая большинства переполнений стека.
/"(?:[^"\\]++|\\.)*+"/
Взято прямо из man perlre в системе Linux с установленным Perl 5.22.0.
В качестве оптимизации это регулярное выражение использует «потенциальную» форму как +, так и * для предотвращения обратного отслеживания, поскольку заранее известно, что строка без закрывающей кавычки ни в коем случае не будет соответствовать.
Он отлично работает на PCRE и не подходит для StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Объяснение:
";.*? {Ленивое совпадение}; оканчивается не escape-символом [^\\];(.*?[^\\])??"), но ей может предшествовать четное число пар знаков escape (\\\\)+; Жадный (!) необязательный: ((\\\\)+)?+ {Жадное сопоставление}, так как строка может быть пустой или без конечных пар!Это не самый эффективный паттерн в мире, но идея интересная. Обратите внимание, что вы можете сократить его так: "(.*?[^\\])?(\\\\)*"
вот тот, который работает с обоими "и", и вы легко добавляете другие в начале.
("|')(?:\\\1|[^\1])*?\1он использует обратную ссылку (\ 1), которая точно соответствует тому, что находится в первой группе ("или").
http://www.regular-expressions.info/backref.html
это очень хорошее решение, но [^\1] следует заменить на ., потому что не существует такой вещи, как обратная ссылка, и это в любом случае не имеет значения. первое условие всегда будет соответствовать до того, как что-нибудь плохое может случиться.
[^\1] на . эффективно изменит это регулярное выражение на ("|').*?\1, а затем оно будет соответствовать "foo\" в "foo \" bar". Тем не менее, заставить [^\1] работать действительно сложно. @ Mathiashansen - Вам будет лучше с громоздким и дорогим (?!\1). (так что все регулярное выражение, с некоторой очисткой эффективности, будет (["'])(?:\\.|(?!\1).)*+\1. + не является обязательным, если ваш движок его не поддерживает.
Вариант, который ранее не затрагивался:
Это дает дополнительный бонус в виде возможности правильно сопоставить закрытые открытые теги.
Допустим, у вас есть следующая строка; 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
)
Вероятно, это намного яснее в форме изображения: сгенерировано с использованием Регулекс Джекса
Изображение на github (Визуализатор регулярных выражений JavaScript.) Извините, у меня недостаточно высокая репутация, чтобы включать изображения, поэтому пока это просто ссылка.
Вот суть примера функции, использующей эту немного более продвинутую концепцию: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
Я столкнулся с аналогичной проблемой при попытке удалить строки в кавычках, которые могут помешать синтаксическому анализу некоторых файлов.
В итоге я получил двухэтапное решение, которое превосходит любое запутанное регулярное выражение, которое вы можете придумать:
line = line.replace("\\\"","\'"); // Replace escaped quotes with something easier to handle
line = line.replaceAll("\"([^\"]*)\"","\"x\""); // Simple is beautiful
Легче читать и, вероятно, более эффективно.
Если ваша IDE - это IntelliJ Idea, вы можете забыть обо всех этих головных болях и сохранить свое регулярное выражение в строковой переменной, и когда вы скопируете и вставите его в двойные кавычки, оно автоматически изменится на приемлемый формат регулярного выражения.
пример на Java:
String s = "\"en_usa\":[^\\,\\}]+";
теперь вы можете использовать эту переменную в своем регулярном выражении или где угодно.
Как найти «Это» в строке, содержащей только «Есть»? Я бы исправил это для вас, но я не знаю, какие соглашения об одинарных кавычках / escape-кодах применяются на используемом вами языке.