Как найти «Это» в строке, содержащей только «Есть»? Я бы исправил это для вас, но я не знаю, какие соглашения об одинарных кавычках / escape-кодах применяются на используемом вами языке.
Собственно, глядя на даты, я вижу, что второй вопрос дублирует этот. В любом случае, обязательно ознакомьтесь с моим ответом .
ridgerunner 08
@ridgerunner: Я голосую за то, чтобы закрыть это, как вы предложили. Верно, что другой вопрос более свежий, но он также намного лучше (в основном благодаря вашему ответу).
Алан Мур
Ответы:
160
/"(?:[^"\\]|\\.)*"/
Работает в Regex Coach и PCRE Workbench.
Пример теста на JavaScript:
var s =' function(){ return " Is big \\"problem\\", \\no? "; }';var m = s.match(/"(?:[^"\\]|\\.)*"/);if(m !=null)
alert(m);
Имеет смысл. Обычный английский: две кавычки, окружающие ноль или более «любого символа, кроме кавычек или обратной косой черты» или «обратной косой черты, за которой следует любой символ». Не могу поверить, что я не думал об этом ...
Ajedi32
7
Я сам отвечу. =) (?:...)- это пассивная или не захватывающая группа. Это означает, что на него нельзя ссылаться позже.
magras
после долгих поисков и тестов это реальное и единственное решение, которое я нашел для этой распространенной проблемы. Спасибо!
Cancebero
10
Спасибо за это. Я также хотел сопоставить одинарные кавычки, поэтому в итоге я адаптировал его к этому:/(["'])(?:[^\1\\]|\\.)*?\1/
c.nanorc был первым местом, куда я пошел. Не удалось заставить его работать как часть строкового литерала C до тех пор, пока он дважды не экранировал все, как это" \"(\\\\.|[^\\\"])*\" "
Hellork
Это работает с функциями egrep и re_comp / re_exec из libc.
fk0
19
Как сообщает ePharaoh, ответ:
/"([^"\\]*(\\.[^"\\]*)*)"/
Чтобы вышеуказанное применялось к строкам в одинарных или двойных кавычках, используйте
Это единственный набор, который у меня работал с одной большой строкой в кавычках размером 1,5 КБ, содержащей 99 экранирований. Все остальные выражения на этой странице в моем текстовом редакторе ломались с ошибкой переполнения. Хотя большинство из них работает в браузере, о чем следует помнить. Fiddle: jsfiddle.net/aow20y0L
Beejor,
3
См. Ответ @ MarcAndrePoulin ниже для объяснения.
shaunc
10
В большинстве представленных здесь решений используются альтернативные пути повторения, например (A | B) *.
Вы можете столкнуться с переполнением стека при больших входных данных, поскольку какой-то компилятор шаблонов реализует это с помощью рекурсии.
Что-то вроде этого:
"(?:[^"\\]*(?:\\.)?)*"или тот, который предоставил Гай Бедфорд, уменьшит количество шагов синтаксического анализа, избегая большинства переполнений стека.
Чередование \"и .пропускает экранированные кавычки, в то время как ленивый квантификатор *?гарантирует, что вы не перейдете за конец строки в кавычках. Работает с классами .NET Framework RE
Взято прямо из man perlreсистемы Linux с установленным Perl 5.22.0. В качестве оптимизации это регулярное выражение использует «потенциальную» форму обоих +и *для предотвращения обратного отслеживания, поскольку заранее известно, что строка без закрывающей кавычки не будет совпадать в любом случае.
Красиво, но слишком гибко для запроса (будет соответствовать одинарным кавычкам ...). И может быть упрощен до /".*?(?<!\)"/, если я что-то не пропущу. Да, и некоторые языки (например, JavaScript), увы, не понимают выражения отрицательного просмотра назад.
PhiLho
1
@PhiLho, простое использование одного (? <! \\) приведет к сбою при экранировании обратной косой черты в конце строки. Однако верно в отношении ретроспективного анализа в JavaScript.
Маркус Джардерот 01
4
Он отлично работает на PCRE и не подходит для StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Объяснение:
Каждая строка в кавычках начинается с Char: ";
Он может содержать любое количество любых символов: .*?{Ленивое совпадение}; оканчивается не escape-символом [^\\];
Оператор (2) является ленивым (!) Необязательным, поскольку строка может быть пустой (""). Так:(.*?[^\\])??
Наконец, каждая строка в кавычках заканчивается Char ( "), но ей может предшествовать четное количество пар знаков escape (\\\\)+; Жадный (!) необязательный: ((\\\\)+)?+{Жадное сопоставление}, так как строка может быть пустой или без конечных пар!
это очень хорошее решение, но его [^\1]следует заменить на, .потому что не существует такой вещи, как анти-обратная ссылка, и это в любом случае не имеет значения. первое условие всегда будет соответствовать, прежде чем что-нибудь плохое может случиться.
Seph Reed
@SephReed - замена [^\1]с .бы эффективно изменить это регулярное выражение для ("|').*?\1а затем он будет соответствовать "foo\"в "foo \" bar". Тем не менее, приступить [^\1]к работе тяжело. @ Mathiashansen - Вам лучше использовать громоздкие и дорогие (?!\1).(так что все регулярное выражение с некоторой очисткой эффективности будет (["'])(?:\\.|(?!\1).)*+\1. +Необязательно, если ваш движок не поддерживает его.
Адам Кац,
2
Вариант, который ранее не затрагивался:
Переверните строку.
Выполните сопоставление перевернутой строки.
Переверните совпавшие струны.
Это дает дополнительный бонус в виде возможности правильно сопоставить закрытые открытые теги.
Допустим, у вас есть следующая строка; 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 =newRegExp(// 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
Следует помнить, что регулярные выражения - не панацея для всего строкового. Некоторые вещи проще сделать с помощью курсора и линейного ручного поиска. CFL будет делать трюк довольно тривиально, но не так много реализаций CFL (AFAIK).
Я столкнулся с аналогичной проблемой при попытке удалить строки в кавычках, которые могут помешать синтаксическому анализу некоторых файлов.
В итоге я получил двухэтапное решение, которое превосходит любое запутанное регулярное выражение, которое вы можете придумать:
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\":[^\\,\\}]+";
теперь вы можете использовать эту переменную в своем регулярном выражении или где угодно.
Ответы:
Работает в Regex Coach и PCRE Workbench.
Пример теста на JavaScript:
источник
(?:...)
- это пассивная или не захватывающая группа. Это означает, что на него нельзя ссылаться позже./(["'])(?:[^\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
Что-то вроде этого:
"(?:[^"\\]*(?:\\.)?)*"
или тот, который предоставил Гай Бедфорд, уменьшит количество шагов синтаксического анализа, избегая большинства переполнений стека.источник
Чередование
\"
и.
пропускает экранированные кавычки, в то время как ленивый квантификатор*?
гарантирует, что вы не перейдете за конец строки в кавычках. Работает с классами .NET Framework REисточник
"\\"
var s = ' my \\"new\\" string and \"this should be matched\"';
/"(?:(?:\\"|[^"])*)"/g
это должно исправитьВзято прямо из
man perlre
системы Linux с установленным Perl 5.22.0. В качестве оптимизации это регулярное выражение использует «потенциальную» форму обоих+
и*
для предотвращения обратного отслеживания, поскольку заранее известно, что строка без закрывающей кавычки не будет совпадать в любом случае.источник
должен работать с любой строкой в кавычках
источник
Он отлично работает на PCRE и не подходит для StackOverflow.
Объяснение:
"
;.*?
{Ленивое совпадение}; оканчивается не escape-символом[^\\]
;(.*?[^\\])??
"
), но ей может предшествовать четное количество пар знаков escape(\\\\)+
; Жадный (!) необязательный:((\\\\)+)?+
{Жадное сопоставление}, так как строка может быть пустой или без конечных пар!источник
"(.*?[^\\])?(\\\\)*"
вот тот, который работает с обоими "и", и вы легко добавляете другие в начале.
он использует обратную ссылку (\ 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\"
не должно.Сначала пример.
Хорошо, теперь объясним, что такое RegExp. Это регулярное выражение можно легко разбить на три части. Следующим образом:
Вероятно, это намного яснее в форме изображения: сгенерировано с помощью Jex Regulex
Изображение на github (Визуализатор регулярных выражений JavaScript). Извините, у меня недостаточно высокая репутация, чтобы включать изображения, поэтому пока это просто ссылка.
Вот суть примера функции, использующей эту более продвинутую концепцию: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
источник
Следует помнить, что регулярные выражения - не панацея для всего строкового. Некоторые вещи проще сделать с помощью курсора и линейного ручного поиска. CFL будет делать трюк довольно тривиально, но не так много реализаций CFL (AFAIK).
источник
Более обширная версия https://stackoverflow.com/a/10786066/1794894
Эта версия также содержит
“
и закрытые”
)источник
Путался в regexpal и закончил с этим регулярным выражением: (Не спрашивайте меня, как это работает, я почти не понимаю, даже хотя я написал это lol)
источник
Если искать с самого начала, может это сработает?
источник
Я столкнулся с аналогичной проблемой при попытке удалить строки в кавычках, которые могут помешать синтаксическому анализу некоторых файлов.
В итоге я получил двухэтапное решение, которое превосходит любое запутанное регулярное выражение, которое вы можете придумать:
Легче читать и, вероятно, более эффективно.
источник
Если ваша IDE - это IntelliJ Idea, вы можете забыть обо всех этих головных болях и сохранить свое регулярное выражение в строковой переменной, и когда вы скопируете его в двойные кавычки, оно автоматически изменится на приемлемый формат регулярного выражения.
пример на Java:
теперь вы можете использовать эту переменную в своем регулярном выражении или где угодно.
источник