Регулярное выражение для соответствия конкретному синтаксису - PullRequest
0 голосов
/ 22 марта 2011

Привет! Я хочу, чтобы шаблон Regex соответствовал очень специфическому строковому синтаксису.Ниже приведена строка Pattern, которую я собрал;это работает в некоторых случаях, но не в других, и я совершенно уверен, что это слишком сложно:

\[\CONTENT\((?:(?:(?:(\w+) ?= ?((?:"(?:[^"]+)")|(?:'(?:[^']+)')|(?:(?:[^"',]+))) ?, ?)+(?:(?:\w+) ?= ?(?:(?:"(?:.+)")|(?:'(?:.+)')|(?:(?:[^"',]+)))))|(?:(?:\w+) ?= ?(?:(?:"(?:.+)")|(?:'(?:.+)')|(?:(?:[^"',]+)))))\)]

Синтаксис строки, который я пытаюсь найти, приведен ниже:

[CONTENT(Name="value, Name2='value2', Name_3 = value3, Name4= "value 4 \" includes an escaped quote")] etc

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

Match Group 1 - Match 1: [CONTENT(Name="value", Name2='value2', Name_3 = value3, Name4= "value 4 \" includes an escaped quote")]

Match Group 2 - Match 1: Name="value"
Match Group 2 - Match 2: Name
Match Group 2 - Match 3: value

Match Group 3 - Match 1: Name2='value'
Match Group 3 - Match 2: Name2
Match Group 3 - Match 3: value2

Match Group 4- Match 1: Name_3 = value3
Match Group 4- Match 2: Name_3
Match Group 4- Match 3: value3

Match Group 5 - Match 1: Name4= "value 4 \" includes an escaped quote"
Match Group 5 - Match 2: Name4
Match Group 5 - Match 3: value 4 \" includes an escaped quote

Когда я имею в виду группы совпадений, я имею в виду группы совпадений в .NET.Результаты не обязательно должны быть такими же, как указано выше, но, по возможности, похожими.

Я довольно хорошо разбираюсь в простом регулярном выражении, но не могу разобраться с осмотром и т. Д.msgstr "наборы могут повторять множество (возможно, но вряд ли неограниченное количество раз), каждое из которых разделено символом ',' (запятая) - за исключением последнего набора (за последним набором имя / значение не будет следовать", "(запятая)).Могут быть пробелы по обе стороны от знака «=» (равно) (или нет), а также по обе стороны от «,» (запятая).

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

Спасибо за любую помощь, которую кто-либо может предоставить.

Chris

Ответы [ 2 ]

1 голос
/ 22 марта 2011

Предполагается ...

  1. Должна быть хотя бы одна пара атрибут / значение.AND
  2. Каждая пара атрибут / значение отделяется одной запятой и необязательным пробелом.AND
  3. Каждое значение атрибута является либо строкой в ​​правильном кавычке, либо одним словом.AND
  4. Строки значений атрибутов в кавычках могут содержать экранированные символы: (например, v1="That's not \"MY\" problem!" и / или v2='That\'s not "MY" problem!').И
  5. Имя атрибута или значение без кавычек «слово» состоит только из букв и тире (т. Е. [A-Za-z0-9_\-]+).(Обратите внимание, что исходный вопрос не определяет это требование четко.)

Тогда это регулярное выражение (в C #) будет правильно соответствовать структуре [CONTENT(a1=v1, a2=v2...)]:

Regex regexObj = new Regex(
    @"# Match a [CONTENT(a1=v1, a2=v2...)] structure.
    \[CONTENT\(\s*                  # Opening delimiter
    # Match required first attrib/value pair.
    [\w\-]+                         # First attrib name (Allow [A-Z-a-z0-9_-].
    \s*=\s*                         # Name and value separated by =.
    (?:                             # Group value spec alternatives.
      ""[^""\\]*(\\.[^""\\]*)*""    # Either double quoted string,
    | '[^'\\]*(\\.[^'\\]*)*'        # or a single quoted string,
    |  [\w\-]+                      # or single unquoted ""word"".
    )                               # End group for value alternatives.
    # Match optional second, third... attrib/value pairs.
    (?:                             # Group to allow optional pairs.
      \s*,\s*                       # All pairs separated by comma.
      [\w\-]+                       # Attrib name.
      \s*=\s*                       # Name and value separated by =.
      (?:                           # Group value spec alternatives.
        ""[^""\\]*(\\.[^""\\]*)*""  # Either double quoted string,
      | '[^'\\]*(\\.[^'\\]*)*'      # or a single quoted string,
      |  [\w\-]+                    # or single unquoted ""word"".
      )                             # End group for value alternatives.
    )*                              # Zero or more optional A=V pairs.
    \s*\)\]                         # Closing delimiter.", 
    RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

Как только высопоставив и захватив одну [CONTENT(...)] структуру, вы можете выделить ее, используя другое регулярное выражение, которое соответствует каждой паре атрибут / значение, по одному за раз.

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

0 голосов
/ 22 марта 2011

Это, конечно, не для регулярных выражений.Вместо этого используйте правильный синтаксический анализатор - очень легко реализовать парсеры рекурсивного спуска с использованием комбинаторов синтаксического анализа в C #.Например, см. это или это .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...