Как поддержать ссылку "внутренний" выбор (()) в регулярном выражении?

Как вернуть обратную внутреннюю скобку в Regex?

Образец данных - это прейскурант продукта, показывающий разные ценовые разрывы на основе приобретенного количества. Формат - количествоLow - количествоHigh: pricePer; кратными.

Я использовал LINQPad для создания этого выражения С# Regex для разделения частей, что показывает удобную визуализацию разделения данных в Regex. В этом примере есть "внутренняя" скобка (выбор), создающая иерархическую структуру данных.

string mys = "1-4:2;5-9:1.89";
Regex.Matches (mys, @"((\d+)[-|\+](\d*):(\d+\.?\d*);?)").Dump();  // Graphically show

Это сводится к (совпадение - это все). Внутри матча есть одно совпадение и групповое совпадение. Внутри группового совпадения есть несколько одиночных совпадений.)

  • MatchCollection (2 элемента)
    • Групповая коллекция (4 предмета)
      • CaptureCollection (1 элемент)() Группа "1-4: 2;"
      • CaptureCollection (1 элемент)() Группа "1"
      • CaptureCollection (1 элемент)() Группа "4"
      • CaptureCollection (1 элемент)() Группа "2"
    • CaptureCollection (1 элемент)() Соответствует "1-4; 2;"
    • Групповая коллекция (4 предмета)
      • CaptureCollection (1 элемент)() Группа "5-9: 1.89"
      • CaptureCollection (1 элемент)() Группа "5"
      • CaptureCollection (1 элемент)() Группа "9"
      • CaptureCollection (1 элемент)() Группа "1.89"
    • CaptureCollection (1 элемент)() Соответствует "5-9: 1.89"

Только для справки:

  • () группа скобок обнаружила результаты, на которые можно ссылаться на \1..\9 (я думаю).
  • \d соответствует одной цифре. + После соответствует одной или нескольким цифрам. * после совпадений ноль или более цифр.? после говорит, что это совпадение необязательно.
  • . соответствует одному символу. \. в этом случае соответствует периоду или десятичному значению.

Ответ 1

Просто используйте \1... \9 (или $1... $9 в некоторых реализациях регулярных выражений), как обычно. Нумерация выполняется слева направо, в зависимости от положения открытого элемента (так что вложенная группа имеет большее число, чем группа (группы), в которую она вложена).

Ответ 2

Обратите внимание, что это ответ на комментарий доктора Зима:

"Как ни странно, оба способа, похоже, работают нормально. Я взял" Регулятор ", который, по крайней мере, показывает, как разбивается регулярное выражение. Если у него есть функция для установки реализации, я думаю, что я в бизнесе".

но мой ответ был слишком длинным для окна комментариев.

Нет, вам не нужно избегать плюса, и в этом случае дефис. Внутри класса символов следующие символы имеют особое значение: ], ^ и -. Эти три символа являются единственными символами, которым может потребоваться экранирование (обратите внимание, что [ не требует экранирования!). Я могу сказать, потому что это зависит от того, где происходят эти метасимволы. ^ имеет особый смысл (как индикатор отрицания) при размещении в начале класса символов, в другом месте он не нуждается в экранировании и будет соответствовать буквальному ^. Примеры для иллюстрации:

[^a]   // special meaning: matches any character except 'a'
[a^]   // matches 'a' or '^'
[\^a]  // matches '^' or 'a'

И дефис имеет особое значение (как индикатор диапазона) при размещении не в начале или конце класса символов. Примеры:

[a-c]  // special meaning: matches 'a', 'b' or 'c'
[ac-]  // matches 'a', 'c' or '-'
[-ac]  // matches '-', 'a' or 'c'
[a\-c] // matches 'a', '-' or 'c'

Несомненно, некоторые реализации регулярных выражений могут отличаться от того, что я только что опубликовал, но большинство языков будет соответствовать этим правилам (на всех языках, с которыми я работал, по крайней мере!). И, как вы заметили, безопасно перебирать символы пробега внутри классов персонажей: это не наносит никакого вреда. Оба класса [+] и [\+] будут соответствовать буквалу +. ИМХО, первый предпочтительнее, потому что я нахожу регулярное выражение со слишком большим количеством проходов, которые трудно читать. Но некоторые не согласятся со мной и обнаруживают, что это лишнее ясность, используя escape (хотя и не обязательно), что буквальный + сопоставляется вместо жадного квантификатора.

Надеюсь, что это очистит.

Ответ 3

В качестве побочного примечания классы символов всегда соответствуют одному символу, и в них не применяются "нормальные" метасимволы. Таким образом, класс [-|\+] соответствует одному из трех символов -, | или +. Как вы видите, логический ИЛИ метасимвол не имеет особого значения внутри класса символов. И вам не нужно избегать символа + внутри класса символов, поэтому это должно сделать это: [-+].