Подтвердить что ты не робот

Как я могу сопоставить строку с разделителями с кавычками с регулярным выражением?

Если я пытаюсь сопоставить строку с разделителями с кавычками с регулярным выражением, какая из следующих "лучше" (где "лучше" означает как более эффективную, так и менее вероятную возможность сделать что-то неожиданное):

/"[^"]+"/ # match quote, then everything that not a quote, then a quote

или

/".+?"/   # match quote, then *anything* (non-greedy), then a quote

Предположим для этого вопроса, что пустые строки (т.е. "") не являются проблемой. Мне кажется (нет новичков регулярных выражений, но, конечно, нет экспертов), что они будут эквивалентны.

Обновить. При отражении, я думаю, что изменение символов + на * будет обрабатывать пустые строки правильно.

4b9b3361

Ответ 1

Вы должны использовать номер один, потому что второй номер - плохая практика. Подумайте, что разработчик, который приходит после вас, хочет сопоставить строки, за которыми следует восклицательный знак. Должен ли он использовать:

"[^"]*"!

или

".*?"!

Разница возникает, если у вас есть тема:

"one" "two"!

Первое регулярное выражение соответствует:

"two"!

а второе регулярное выражение:

"one" "two"!

Всегда будьте как можно более конкретными. Используйте отрицательный класс символов, когда сможете.

Другое отличие состоит в том, что [^ "] * может охватывать строки, а. * не работает, если вы не используете однострочный режим. [^" \n] * также исключает разрывы строк.

Что касается обратного слежения, то для второго и второго символов регулярных выражений для каждого символа в каждой строке соответствует. Если закрывающая цитата отсутствует, оба regexes будут возвращаться через весь файл. Только порядок, в котором происходит откат, отличается. Таким образом, теоретически первое регулярное выражение выполняется быстрее. На практике вы не заметите разницы.

Ответ 2

Я бы предложил:

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

Но только потому, что он обрабатывает экранированные символы кавычек и позволяет и "и" быть цитатой char. Я также хотел бы взглянуть на эту статью, которая углубляется в эту проблему:

http://blog.stevenlevithan.com/archives/match-quoted-string

Однако, если у вас нет серьезной проблемы с производительностью или вы не можете быть уверены в встроенных кавычках, используйте более простой и понятный:

/".*?"/

Я должен признать, что нежелательные шаблоны не являются основным регулярным выражением в стиле Unix, но они становятся довольно распространенными. Я до сих пор не привык группировать операторы типа (?: Stuff).

Ответ 3

Сложнее, но он обрабатывает экранированные кавычки и также сбрасывает обратную косую черту (escape-обратная косая черта с последующей цитатой не является проблемой)

/(["'])((\\{2})*|(.*?[^\\](\\{2})*))\1/

Примеры:
  "привет \" мир " соответствует " привет\ "мир"
  "привет \\" мир " соответствует " привет\\"

Ответ 4

Я бы сказал, что второй лучше, потому что он не работает быстрее, когда отсутствует завершающий ". Первый из них будет возвращаться по струне, что является потенциально дорогостоящей операцией. Альтернативное регулярное выражение, если вы используете perl 5.10, будет /"[^"]++"/. Он передает то же значение, что и в версии 1, но так же быстро, как и версия 2.

Ответ 5

Я бы выбрал номер два, так как его было намного легче читать. Но мне все равно хотелось бы совместить пустые строки, поэтому я бы использовал:

/".*?"/

Ответ 6

С точки зрения производительности (чрезвычайно тяжелая, длинная петля над длинными строками) я мог представить, что

"[^"]*"

быстрее, чем

".*?"

потому что последний выполнил дополнительную проверку для каждого шага: заглядывая в следующий символ. Первый сможет бездумно перевернуть строку.

Как я уже сказал, в реальных сценариях это вряд ли будет заметно. Поэтому я бы пошел с номером два (если мой текущий аромат регулярного выражения поддерживает его, то есть), потому что он гораздо читабельнее. Иначе, конечно, номер один.

Ответ 7

Использование отрицаемого символьного класса предотвращает совпадение, когда граничный символ (двойные значения в вашем примере) присутствует в другом месте ввода.

Ваш пример # 1:

/"[^"]+"/ # match quote, then everything that not a quote, then a quote

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

К счастью, Дамиан Конвей готов со спасением: Text:: Balanced существует для вас, если вы обнаружите, что есть несколько совпадающих цитат Метки. Он также имеет преимущество при сопоставлении другой парной пунктуации, например. круглые скобки.

Ответ 8

Я предпочитаю первое регулярное выражение, но это, безусловно, вопрос вкуса.

Первый может быть более эффективным?

Search for double-quote
add double-quote to group
for each char:
    if double-quote:
        break
    add to group
add double-quote to group

Что-то более сложное, связанное с обратным отслеживанием?

Ответ 9

Учитывая, что я даже не знал о "*?" до сегодняшнего дня, и я использую регулярные выражения в течение более 20 лет, я проголосовал бы за первое. Это, безусловно, дает понять, что вы пытаетесь сделать - вы пытаетесь сопоставить строку, которая не включает кавычки.