Как я могу сопоставить строку с разделителями с кавычками с регулярным выражением?
Если я пытаюсь сопоставить строку с разделителями с кавычками с регулярным выражением, какая из следующих "лучше" (где "лучше" означает как более эффективную, так и менее вероятную возможность сделать что-то неожиданное):
/"[^"]+"/ # match quote, then everything that not a quote, then a quote
или
/".+?"/ # match quote, then *anything* (non-greedy), then a quote
Предположим для этого вопроса, что пустые строки (т.е. "") не являются проблемой. Мне кажется (нет новичков регулярных выражений, но, конечно, нет экспертов), что они будут эквивалентны.
Обновить. При отражении, я думаю, что изменение символов +
на *
будет обрабатывать пустые строки правильно.
Ответы
Ответ 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 лет, я проголосовал бы за первое. Это, безусловно, дает понять, что вы пытаетесь сделать - вы пытаетесь сопоставить строку, которая не включает кавычки.