я пытаюсь разбить строку через пробелы, но не разбивать всё что заключено в скобки ()
Данный код работает нормально для (a + b) * c * (x - y) ==> (a + b), *, c, *, (x - y)
Regex.Matches(expression, @"[\(].+?[\)]|[^ ]+")
.Cast<Match>()
.Select(m => m.Value)
.ToArray();
Но этот пример разбивается не так как я ожидаю...
(a * (x - y)) * c
Получается: (a * (x - y), ), *, с Ожидается: (a * (x - y)), *, с
Я уже второй день ломаю голову, что бы правильно разбить, но никак не получается. Я думаю надо сделать что бы закрывающая скобка [\)]
засчитывалась только если после нее нету такой же скобки без открывающей перед ней :-)
Но вот не могу написать такое выражение...
Используйте "balanced construct":
Regex.Matches(s, @"(?x)
\( # открывающая круглая скобка
(?> # начало группы, которая находит...
[^()]+| # 1+ символов, отличных от круглых скобок
(?<o>)\(| # открывающая круглая скобка (пустая строка добавляется в стек группы `o`)
(?<-o>)\) # закрывающая круглая скобка (пустая строка удаляется из стека группы `o`)
)* # повторить 0 и более раз
(?(o)(?!)) # если в стеке группы `o` остались значения, отменить совпадение
\) # закрывающая круглая скобка
| # или
[^\s()]+ # 1+ символов, отличных от пробельных и круглых скобок
")
.Cast<Match>()
.Select(m => m.Value)
.ToArray();
См. демо регулярного выражения, а здесь демо C#.
Подробности
\(
- открывающая круглая скобка(?>
- начало группы, которая находит...
[^()]+|
- 1+ символов, отличных от круглых скобок(?<o>)\(|
- открывающая круглая скобка (пустая строка добавляется в стек группы o
)(?<-o>)\)
- закрывающая круглая скобка (пустая строка удаляется из стека группы o
))*
- повторить 0 и более раз(?(o)(?!))
- если в стеке группы o
остались значения, отменить совпадение\)
- закрывающая круглая скобка|
- или[^\s()]+
- 1+ символов, отличных от пробельных и круглых скобок.Если задача просто разбить строку по пробелам, то можно попробовать и без регулярок это сделать. Например так
IEnumerable<string> Split(string input)
{
var counter = 0;
var startPos = 0;
List<string> parts = new List<string>();
for (var i = 0; i < input.Length; i++)
{
var c = input[i];
if (c == ' ' && counter == 0)
{
var len = i - startPos;
if (len > 0)
{
parts.Add(input.Substring(startPos, len));
}
startPos = i+1;
}
if (c == '(') counter++;
if (c == ')') counter--;
}
var lastInd = input.Length;
var lastLen = lastInd - startPos;
if (lastLen > 0) parts.Add(input.Substring(startPos, lastLen ));
return parts;
}
Да, кода больше, но имхо он понятней, чем регулярка, да и работает в теории побыстрее.
Вариант с ленивым вычислением. Пользоваться можно также, как первым вариантом.
IEnumerable<string> Split(string input)
{
var counter = 0;
var startPos = 0;
for (var i = 0; i < input.Length; i++)
{
var c = input[i];
if (c == ' ' && counter == 0)
{
var len = i - startPos;
if (len > 0)
{
yield return input.Substring(startPos, len);
}
startPos = i+1;
}
if (c == '(') counter++;
if (c == ')') counter--;
}
var lastInd = input.Length;
var lastLen = lastInd - startPos;
if (lastLen > 0) yield return input.Substring(startPos, lastLen);
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть контроллер, работающий по протоколу modbus rtuНужно к нему написать приложение для опроса
И так, недавно мной был задан вопрос насчет простого GET запроса с исполнением скриптовСейчас я работаю над несколькими проектами, тема у них...