2015-08-05 2 views
0

Я пытаюсь сопоставить подстроки, заключенные в {...}, где внутреннее содержимое представляет собой набор n-кортежей, каждый из которых разделен запятой (пример показан ниже). Шаблон регулярного выражения получает ожидаемый результат, но не полностью выражает все необходимые правила.C# Regex - сопоставление списка с разделителями-запятыми

Правила

  • Brace: подстроки, заключенные в {...}, но не вложенные фигурные скобки суб, таких как { ... {..}}
  • Comma: Элемент {(a,b)(t,s),(u,v)} не в матчах, так как он отсутствует запятая между (a,b) и (t,s).
  • Tuple: Элементы n-кортежа могут быть любыми текстами, не содержащими запятую или скобки или скобки. Например: (a,b, test element) это нормально, но не (a,b, {ab})

Но регулярное выражение шаблон используется не совсем работает.

Например, если перенести запятую в {(a,b)(t,s),(u,v)}, чтобы сделать его {(a,b),(t,s)(u,v)} этот элемент появляется как матч, хотя теперь кортежи (t,s) и (u,v) не разделены запятой.

Допустимыми Результаты

{(а, б, в), (д, д, е), (R, S и Q, T), (U, V, у)}

{(а, б), (в, г, д)}

{(а, б), (с + 1, d)}

string st = 
"abc+{(a,b,c),(d,e,f),(r,s and q,t),(u,v,y)}+c-{(a,b)(t,s),(u,v)}+e+{(a,b),(c,d,e)}+rst+{(a,b),(c,d)}"; 

Regex oRegex = new Regex(@"{\([^\)\(]+\)[,]+\(.*?\)}"); 

foreach (Match mt in oRegex.Matches(st)) 
    Console.WriteLine(mt.Value); 
+0

Похоже, вы пытаетесь разобрать язык, а не что-то, что легко анализируется регулярным выражением. Возможно, вам лучше использовать полноразмерный парсер с вашей собственной грамматикой https://github.com/picoe/Eto.Parse –

+0

Вы уверены, что какой-либо текст не содержит запятую? Будет ли что-то вроде '(a, b, {ab})' совпадением? – ataravati

+0

@ataravati Хорошая точка. Нет встроенных скобок или скобок. Например. ничего подобного (a, b, (ab)) тоже. Позвольте мне обновить свой пост. – nam

ответ

0

Ваше выражение имеет более проб лемы. Ниже будут появляться также матчи, которые я не думаю, что это то, что вы хотите:

{(а ,, Ь), (с ,, d)}

{(а, б) ,, (в, г, д)}

{(а, ABCD), (ABCD, б)}

Попробуйте этот:

Regex oRegex = new Regex(@"{\(\w(,\w)*\)(,\(\w(,\w)*\))*}"); 

UPDATE: Если элементы кортежей может быть любой текст, не содержащий запятой или фигурные скобки или скобки, то вы можете попробовать это:

Regex oRegex = new Regex(@"{\([^,(){}]+(,[^,(){}]+)*\)(,\([^,(){}]+(,[^,(){}]+)*\))*}"); 

И, если бело-пространство вокруг запятых между кортежи в порядке (например,{(a,b), (c,d)}), то вы можете использовать это:

Regex oRegex = new Regex(@"{\([^,(){}]+(,[^,(){}]+)*\)(\s*,\s*\([^,(){}]+(,[^,(){}]+)*\))*}"); 

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

+0

Я должен был упомянуть, что элементами n-кортежа может быть любой текст, не содержащий запятой. Я отредактировал свой пример и добавил EDIT в конце своего исходного сообщения – nam

+2

@nam Просто измените '\ w' на' [^,() {}] '(хотя вам может понадобиться еще больше ограничить набор символов, так как он позволяет остальной Юникод там). – nhahtdh

+0

@nam, проверьте мой обновленный ответ. – ataravati

Смежные вопросы