Как получить подстроку " It's big \"problem "
с помощью регулярного выражения?
s = ' function(){ return " It\'s big \"problem "; }';
Как получить подстроку " It's big \"problem "
с помощью регулярного выражения?
s = ' function(){ return " It\'s big \"problem "; }';
Ответы:
/"(?:[^"\\]|\\.)*"/
Работает в 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\"';
этом такой подход приведет к неожиданным результатам.
Это происходит из nanorc.sample, доступного во многих дистрибутивах Linux. Используется для подсветки синтаксиса строк в стиле C
\"(\\.|[^\"])*\"
var s = ' my \\"new\\" string and \"this should be matched\"';
этом такой подход приведет к неожиданным результатам.
" \"(\\\\.|[^\\\"])*\" "
Как сообщает ePharaoh, ответ:
/"([^"\\]*(\\.[^"\\]*)*)"/
Чтобы вышеуказанное применялось к строкам в одинарных или двойных кавычках, используйте
/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
В большинстве представленных здесь решений используются альтернативные пути повторения, например (A | B) *.
Вы можете столкнуться с переполнением стека при больших входных данных, поскольку какой-то компилятор шаблонов реализует это с помощью рекурсии.
Например, Java: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993
Что-то вроде этого:
"(?:[^"\\]*(?:\\.)?)*"
или тот, который предоставил Гай Бедфорд, уменьшит количество шагов синтаксического анализа, избегая большинства переполнений стека.
/"(?:[^"\\]++|\\.)*+"/
Взято прямо из man perlre
системы Linux с установленным Perl 5.22.0. В качестве оптимизации это регулярное выражение использует «потенциальную» форму обоих +
и *
для предотвращения обратного отслеживания, поскольку заранее известно, что строка без закрывающей кавычки не будет совпадать в любом случае.
/(["\']).*?(?<!\\)(\\\\)*\1/is
должен работать с любой строкой в кавычках
Он отлично работает на PCRE и не подходит для StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Объяснение:
"
;.*?
{Ленивое совпадение}; оканчивается не escape-символом [^\\]
;(.*?[^\\])??
"
), но ей может предшествовать четное количество пар знаков escape (\\\\)+
; Жадный (!) необязательный: ((\\\\)+)?+
{Жадное сопоставление}, так как строка может быть пустой или без конечных пар!"(.*?[^\\])?(\\\\)*"
вот тот, который работает с обоими "и", и вы легко добавляете другие в начале.
( "|") (: \\\ 1 | [^ \ 1])? * \ 1
он использует обратную ссылку (\ 1) в точном соответствии с тем, что находится в первой группе ("или").
[^\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
)
Вероятно, это намного яснее в форме изображения: сгенерировано с помощью Jex Regulex
Изображение на github (Визуализатор регулярных выражений JavaScript). Извините, у меня недостаточно высокая репутация, чтобы включать изображения, поэтому пока это просто ссылка.
Вот суть примера функции, использующей эту более продвинутую концепцию: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
Следует помнить, что регулярные выражения - не панацея для всего строкового. Некоторые вещи проще сделать с помощью курсора и линейного ручного поиска. CFL будет делать трюк довольно тривиально, но не так много реализаций CFL (AFAIK).
Более обширная версия https://stackoverflow.com/a/10786066/1794894
/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/
Эта версия также содержит
“
и закрытые ”
)Если искать с самого начала, может это сработает?
\"((\\\")|[^\\])*\"
Я столкнулся с аналогичной проблемой при попытке удалить строки в кавычках, которые могут помешать синтаксическому анализу некоторых файлов.
В итоге я получил двухэтапное решение, которое превосходит любое запутанное регулярное выражение, которое вы можете придумать:
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\":[^\\,\\}]+";
теперь вы можете использовать эту переменную в своем регулярном выражении или где угодно.