Regex: найти все кавычки (учитывая экранированные кавычки) [duplicate]

это фрагмент, который я использую, он удаляет все вещи между APA и BEPA (через несколько строк, включая удаление APA, BEPA) во всех файлах ниже текущего каталога, исключает каталог .svn

find . \! -path '*.svn*' -type f -exec sed -i -n '1h;1!H;${;g;s/APA[ \t\r\n]*BEPA//g;p}' {} \;
88
задан David 30 January 2015 в 17:22
поделиться

14 ответов

/"(?:[^"\\]++|\\.)*+"/

Взято прямо из man perlre в системе Linux с установленным Perl 5.22.0. В качестве оптимизации это регулярное выражение использует «posessive» форму как +, так и * для предотвращения обратного отслеживания, поскольку заранее известно, что строка без закрывающей цитаты не будет соответствовать ни в коем случае.

5
ответ дан ack 16 August 2018 в 05:30
поделиться

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

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

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

  1. Минимальная длина цитаты 50
  2. Экстра-тип кавычек (открыть и закрыть )
0
ответ дан Community 16 August 2018 в 05:30
поделиться

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

\"((\\\")|[^\\])*\"
0
ответ дан cxw 16 August 2018 в 05:30
поделиться

Как указано в ePharaoh, ответ:

/"([^"\\]*(\\.[^"\\]*)*)"/

Чтобы применить вышеприведенные к одиночным или двойным кавычками строки, используйте

/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
13
ответ дан Guy Bedford 16 August 2018 в 05:30
поделиться
  • 1
    Это единственный набор, который работал для меня с одной большой строкой длиной 1.5 KB, содержащей 99 побегов. Каждое другое выражение на этой странице разбилось на мой текстовый редактор с ошибкой переполнения. Хотя большинство из них работают в браузере, просто нужно иметь в виду. Fiddle: jsfiddle.net/aow20y0L – Beejor 4 June 2015 в 03:00
  • 2
    См. Ответ @ MarcAndrePoulin ниже для объяснения. – shaunc 7 August 2015 в 21:00

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

0
ответ дан Henrik Paul 16 August 2018 в 05:30
поделиться
  • 1
    Достаточно, но эта проблема хорошо находится в пределах возможностей регулярных выражений, и их много. – Alan Moore 30 October 2008 в 17:45

Большинство предлагаемых решений используют альтернативные пути повторения, т. е. (A | B) *.

Вы можете столкнуться с переполнением стека на больших входах, поскольку какой-то компилятор шаблонов реализует это с помощью рекурсии.

Java, например: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993

Что-то вроде этого: "(?:[^"\\]*(?:\\.)?)*" или один предоставленный Гаем Бедфордом, уменьшит количество шагов синтаксического анализа, избегая большинства переполнений стека.

8
ответ дан Marc-André Poulin 16 August 2018 в 05:30
поделиться

здесь работает тот, который работает с «и», и вы легко добавляете других в начале.

("|')(?:\\\1|[^\1])*?\1

он использует обратную ссылку (\ 1), чтобы точно совместить то, что находится в первой группе (" или ').

http://www.regular-expressions.info/backref.html

1
ответ дан mathias hansen 16 August 2018 в 05:30
поделиться
  • 1
    это очень хорошее решение, но [^\1] следует заменить на ., потому что нет такой вещи, как анти-обратная ссылка, и это не имеет никакого значения. первое условие всегда будет соответствовать, прежде чем произойдет что-либо плохое. – Seph Reed 2 November 2017 в 07:15

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

"(([^"\\]?(\\\\)?)|(\\")+)+"
0
ответ дан Petter Thowsen 16 August 2018 в 05:30
поделиться
/"(?:[^"\\]|\\.)*"/

Работает в Regex Coach и PCRE Workbench.

Пример теста в JavaScript:

    var s = ' function(){ return " Is big \\"problem\\", \\no? "; }';
    var m = s.match(/"(?:[^"\\]|\\.)*"/);
    if (m != null)
        alert(m);

112
ответ дан Philip Kirkbride 16 August 2018 в 05:30
поделиться
  • 1
    Имеет смысл. Обычный английский: две кавычки, окружающие нуль или более "любого символа, который не является котировкой или обратной косой чертой" или "обратную косую черту с последующим символом". Не могу поверить, что я не думал об этом ... – Ajedi32 4 January 2014 в 00:17
  • 2
    Что означает ?:? – magras 2 October 2014 в 14:38
  • 3
    Я отвечу сам. =) (?:...) - пассивная или не захватывающая группа. Это означает, что он не может быть обратный позже. – magras 2 October 2014 в 17:27
  • 4
    Спасибо за это. я тоже хотел сопоставить одинарные кавычки, поэтому я решил адаптировать его к этому: /(["'])(?:[^\1\\]|\\.)*?\1/ – leo 3 May 2015 в 02:47
  • 5
    Вот Regexr с объяснением: regexr.com/3bqg1 – Tomáš Fejfar 18 September 2015 в 07:10

Опция, которая ранее не была затронута:

  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 = 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 Regular Expression Visualizer.) Извините, у меня нет достаточно высокой репутации, чтобы включить изображения, поэтому на данный момент это только ссылка.

Вот суть примерной функции, использующей эту концепцию это немного более продвинуто: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js

0
ответ дан scagood 16 August 2018 в 05:30
поделиться
"(?:\\"|.)*?"

Чередование \" и . проходит через экранированные кавычки, в то время как ленивый квантификатор *? гарантирует, что вы не проходите мимо конца строки с кавычками. Работает с классами .NET Framework RE

8
ответ дан Tosh Afanasiev 16 August 2018 в 05:30
поделиться
/(["\']).*?(?<!\\)(\\\\)*\1/is

должен работать с любой цитируемой строкой

3
ответ дан user 16 August 2018 в 05:30
поделиться
  • 1
    Хороший, но слишком гибкий для запроса (будет соответствовать одинарным кавычкам ...). И может быть упрощено до /".*?(?<!\)"/, если я не пропущу что-то. О, и некоторые языки (например, JavaScript) увы не понимают негативных выражений lookbehind. – PhiLho 30 October 2008 в 13:47
  • 2
    @PhiLho, просто использование одного (? & Lt;! \\) завершится неудачей при сбрасываемых обратных косых чертах в конце строки. Правда о взглядах на JavaScript в JavaScript. – Markus Jarderot 1 November 2008 в 09:57
  • 3
    круто! хорошо работает с цитатой "!!! – LINKeRxUA 25 May 2016 в 09:14
  • 4
    С помощью var s = ' my \\"new\\" string and \"this should be matched\"'; этот подход приведет к неожиданным результатам. – Wiktor Stribiżew 25 July 2016 в 12:38

Это работает отлично на PCRE и не падает с помощью StackOverflow.

"(.*?[^\\])??((\\\\)+)?+"

Объяснение:

  1. Каждая строка с кавычками начинается с Char: ";
  2. Он может содержать любое количество символов: .*? {Lazy match}; завершение символом non escape [^\\];
  3. Оператор (2) является Lazy (!) необязательным, потому что строка может быть пустой (""). Итак: (.*?[^\\])??
  4. Наконец, каждая строка с кавычками заканчивается символом Char ("), но ему может предшествовать четное число пар escape-пар (\\\\)+; и это Greedy (!) необязательно: ((\\\\)+)?+ {Greedy matching}, строка bacause может быть пустой или без конечных пар!
4
ответ дан Vadim Sayfi 16 August 2018 в 05:30
поделиться
  • 1
    Это не самый эффективный образец мира, но идея интересная. Обратите внимание, что вы можете сократить его следующим образом: "(.*?[^\\])?(\\\\)*" – Casimir et Hippolyte 17 March 2018 в 22:59

Я столкнулся с аналогичной проблемой, пытающейся удалить строки с кавычками, которые могут помешать анализу некоторых файлов.

Я закончил с двухступенчатым решением, которое превосходит любое запутанное регулярное выражение, которое вы можете найти: / g1]

 line = line.replace("\\\"","\'"); // Replace escaped quotes with something easier to handle
 line = line.replaceAll("\"([^\"]*)\"","\"x\""); // Simple is beautiful

Легче читать и, вероятно, более эффективно.

0
ответ дан マルちゃん だよ 16 August 2018 в 05:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: