2016-01-13 3 views
1

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

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

 Regex re = new Regex(@"(\,|\(|\)|(-?\d*\.?\d+e[+-]?\d+)|\+|\-|\*|\^)"); 
    var tokens = re.Split(equation) 

так что уравнения, такие как

2.75423E-19* (var1-5)^(1.17)* (var2)^(1.86)* (var3)^(3.56) 

должен разобрать, чтобы

 [2.75423E-19 ,*, (, var1,-,5,), ^,(,1.17,),*....,3.56,)] 

Однако й e экспоненциальная часть также разделяется, что, я думаю, связано с частью регулярного выражения: | + | -.

Другие выдач я попытался это:

Regex re1 = new Regex(@"([\,\+\-\*\(\)\^\/\ ])"); and 
    Regex re = new Regex(@"(-?\d*\.?\d+e[+-]?\d+)|([\,\+\-\*\(\)\^\/\ ])"); 

, которые оба имеют там недостатки. Любая помощь будет оценена по достоинству.

+1

Как вы планируете дистанционно устранить минус с отрицательными значениями и как арифметический оператор? Или это не нужно здесь? BTW, проверьте ['[0-9] * \.? [0-9] + ([eE] [- +]? [0-9] +)? | [-^+ * /()] | \ w + '] (http://regexstorm.net/tester?p=%5b0-9%5d*%5c.%3f%5b0-9%5d%2b (% 5beE% 5d% 5b-% 2b% 5d% 3f% 5b0-9% 5d% 2b)% 3f% 7c% 5b-% 5e% * 2b% 2f()% 5d% 7c% 5cw% 2b & я = 2.75423E-19 * + (var1-5)% 5e (1,17) * + (var2)% 5e (1.86) * + (var3)% 5e (3.56)), который * соответствует * токенам. –

+2

IMHO Я считаю, что вам лучше разобраться в правильном механизме синтаксического анализа. –

+0

@stribizhev вы должны опубликовать это как ответ, так как он правильно маркирует текст. Кстати, при арифметическом разборе вы обычно не имеете дело с маркерами отрицательного числа, но обрабатываете числа как положительное число с унарным оператором минус. И для OP, если вам нужно написать собственный парсер, вы можете быть заинтересованы в [этом ответе], или, может быть, вы можете использовать что-то вроде [NCalc] (https://ncalc.codeplex.com/), если оно подходит твои нужды. –

ответ

0

Так что я думаю, что у меня есть решение, благодаря @stribizhev решение приведет меня к регулярному выражению решения

  Regex re = new Regex(@"(\d+(,\d+)*(?:.\d+)?(?:[eE][-+]?[0-9]+)?|[-^+/()]|\w+)"); 
      tokenList = re.Split(InfixExpression).Select(t => t.Trim()).Where(t => t != "").ToList(); 

После разделения дает мне нужный массив.

2

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

[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?|[-^+*/()]|\w+ 

См regex demo

регулярное выражение матча:

  • [0-9]*\.?[0-9]+([eE][-+]?[0-9]+)? - поплавок номер
  • | - или ...
  • [-^+*/()] - любой из арифметических и логических операторов, присутствующих в уравнении размещены
  • | - или ...
  • \w+ - 1 или более слов символов (буквы, цифры или подчеркивания).

Для более сложной токенизации, рассмотреть вопрос об использовании NCalc предложенного Lucas Trzesniewski «s comment.

C# sample code:

var line = "2.75423E-19* (var1-5)^(1.17)* (var2)^(1.86)* (var3)^(3.56)"; 
var matches = Regex.Matches(line, @"[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?|[-^+*/()]|\w+"); 
foreach (Match m in matches) 
    Console.WriteLine(m.Value); 

И обновленный код для вас, чтобы показать, что Regex.Split не нужно здесь:

var result = Regex.Matches(line, @"\d+(?:[,.]\d+)*(?:e[-+]?\d+)?|[-^+*/()]|\w+", RegexOptions.IgnoreCase) 
      .Cast<Match>() 
      .Select(p => p.Value) 
      .ToList(); 

Кроме того, в соответствии отформатированные номера, вы можете использовать \d+(?:[,.]\d+)* вместо [0-9]*\.?[0-9]+ или \d+(,\d+)* ,

+0

Спасибо за ваше решение, однако я все еще не совсем уверен, что это правильно. Хотя демон regex показывает, что все правильные элементы, которые совпадали, когда я реализовал его и разделил выражение, я получаю дополнительный элемент E-19 в моем массиве. Возможно, это мое недопонимание библиотеки регулярных выражений, я полагаю, я мог бы перебирать коллекцию матчей, однако это может привести к непредвиденным проблемам при реализации других уравнений. –

+0

@Jnewson вы использовали строковый синтаксис для передачи шаблона? '@ "[0-9] * \ [0-9] + ([еЕ] [- +] [0-9] +?) |.? [-^+ * /()] |? \ Ш +"' - как это? –

+0

@ Lucas Trzesniewski Мне пришлось добавить его как группу @ "([0-9] * \.? [0-9] + ([eE] [- +]? [0-9] +)? | [-^+ * /,()] | \ w +) ", чтобы получить результат, иначе я получил пустой массив, когда я выполнил split. –