Регулярное выражение для сопоставления экранируемых строк?

#.net #regex #balancing-groups

#.net #регулярное выражение #балансировка-группы

Вопрос:

Я написал это регулярное выражение для сопоставления строк:

 (?>(?<Quote>""|').*?(?<!\)k<Quote>)
  

т.е. некоторый текст, заключенный в кавычки. Он также поддерживает экранирование, поэтому он будет соответствовать "hello"world" полностью, не останавливаясь на первой кавычке, как я хочу. Но я забыл о двойном экранировании. "hello\"world" недопустимо, например.

Я почти уверен, что это можно исправить с помощью балансирующих групп, но я никогда раньше ими не пользовался. Кто-нибудь знает, как это написать?

Ответ №1:

Регулярные выражения не предназначены для использования с экранируемыми конструкциями.

Я не думаю, что это возможно сделать каким-либо «приятным» способом (если вообще возможно), хотя я опубликую правку, если выясню иное.

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


Редактировать 1:

Это зависит от того, сколько функций вы ищете. Если вы просто хотите сопоставить следующую экранируемую цитату, вы можете использовать шаблон

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

которое при экранировании для кода получается как

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

для сопоставления чего-то вроде

 "Hello! " Hi! " "
  

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


Правка 2:

Если вам интересно, как в любом случае работают определения балансирующих групп, я рекомендую прочитать страницу 430 этой книги (34 в формате pdf).

Комментарии:

1. Мне потребовалось несколько минут, чтобы понять, что вы экранировали это регулярное выражение для использования в коде… это просто сбивает с толку. Должно быть "((?>[^\"]|\.)*)" . Почему балансирующие группы могут использоваться только для вложенных конструкций? Мы хотим сбалансировать количество косых черт, нет? Заключительная цитата должна быть дополнена четным числом косых черт или не должна быть дополнена нечетным числом. Я не хочу делать это позади, потому что это часть гораздо большего регулярного выражения.

2. @Mark: Да, извините, это было экранировано. : ( Редактировать: я сделал это немного более читабельным.) Здесь вам не нужна никакая балансировка, потому что вы ничего не пытаетесь «сбалансировать» — все, что вы говорите, это «строка — это последовательность неэкран-символов и / или экранированных символов», которая выполняется за один проход. Нет необходимости что-либо где-либо балансировать. (Я не уверен, что вы подразумеваете под четными / нечетными косыми чертами … не могли бы вы объяснить, что вы имеете в виду?)

3. На самом деле я думаю, что ему нужно всего 2 косых черты в [] . По четному / нечетному… Я имею в виду, что "hello"world" должно совпадать (1 косая черта), но "hello\"world" также должно совпадать (3 косых черты). 1-я косая черта экранирует 2-ю, а 3-я экранирует кавычку. итак, если перед цитатой нечетное количество косых черт, то она считается экранированной.

4. Кроме того, я думаю, что это намного проще читать с обозначением @-quote: @"""((?>[^\""]|\.)*)""" . Ну … немного проще. Это немного неудачный пример, потому что он также имеет дело с кавычками, но, по крайней мере, косые черты не смешны.

5. @Mark: Да, они оба работали, я не был уверен, " было ли это особенным или нет, поэтому я избежал этого. Что касается четного / нечетного: это на самом деле делает то, что вы хотите! Вы просто забыли заключить все это в кавычки ( ""hello\"world"" ). И да, я пробовал использовать дословные строки, но они были не намного лучше, неважно. (Кстати, это обратная косая черта, а не косые черты. : P)