Мне нужно разобрать список номеров и номеров номеров, разделенных запятыми. Строки вводятся в пользовательском интерфейсе пользователем и будет выглядеть как один из них (шесть различных образцов входов):.NET Regex выражение для разбора списка чисел и диапазонов чисел
1-3, 5, 7-10
1
21.1
1.2-3,5.1,7-10.1
1-3, 5.1, 7-10, 21
1.1-3.1,5.1,7.1-10.1
Моя конечная цель иметь коллекцию числа и числа диапазонов, которые можно обработать позже вниз по течению , Например, после разбора первого образца строки выше моего конечного результата будет сбор, содержащий 3 элемента: 1-3, 5 и 7-10.
Использование C# и .NET Regex эта модель хорошо заполняет коллекцию соответствий с только пункты мне нужно (Обратите внимание на использование не-захвата групп):
(\d+(?:\.\d+)?-\d+(?:\.\d+)?)|(\d+(?:\.\d+)?)
У меня есть два вопроса, хотя:
Нужно ли мне все это в моем шаблоне или существует ли более короткий шаблон?
Есть ли что-то, что я могу добавить к шаблону, чтобы возвращать 0 совпадений, когда есть недопустимые символы, содержащиеся в строке? Например, если я включаю альфа-символ в строку в любом месте, я бы не хотел, чтобы совпадения не встречались. Сейчас я делаю это с двумя проходами, один для проверки того, что строка имеет только допустимые символы [\ d, .-] и другой проход, чтобы получить совпадения, предполагающие, что они подтверждены в первом проходе.
Заранее благодарим за идеи.
Update:
Вот решение, которое я в конечном итоге происходит с (см @ Xiaoy312 ответ):
public static IEnumerable<DataRange> ParseInput(string input)
{
if (!Regex.IsMatch(input.Replace(" ", string.Empty), @"^[\d\.,\-]+$"))
return Enumerable.Empty<DataRange>();
return Regex.Matches(input.Replace(" ", string.Empty),
@"(?<A>\d+(?:\.\d+)?)(?:-(?<B>\d+(?:\.\d+)?))?").Cast<Match>()
.Select(m => new DataRange
{
A = double.Parse(m.Groups["A"].Value,
System.Globalization.CultureInfo.InvariantCulture),
B = m.Groups["B"].Success ? double.Parse(m.Groups["B"].Value,
System.Globalization.CultureInfo.InvariantCulture) : (double?)null
});
}
public class DataRange
{
public double A;
public double? B;
}
Вот пример использования: выход
static void Main(string[] args)
{
Console.WriteLine("A\tB");
var items = ParseInput("1");
Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
items = ParseInput("21.1");
Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
items = ParseInput("1-3,5,7-10");
Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
items = ParseInput("1.2-3,5.1,7-10.1");
Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
items = ParseInput("1-3, 5.1, 7-10,21");
Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
items = ParseInput("1.1-3.1,5.1,7.1-10.1");
Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
items = ParseInput("1.1-3.1,5.1,7.1-10.1a");
Array.ForEach(items.ToArray(), i => Console.WriteLine("{0}\t{1}", i.A, i.B));
}
Пример:
A B
1
21.1
1 3
5
7 10
1.2 3
5.1
7 10.1
1 3
5.1
7 10
21
1.1 3.1
5.1
7.1 10.1
Что вы делаете, что не может быть достигнуто с двумя или три ['String.Split()'] (http://msdn.microsoft.com/en-us /library/system.string.split%28v=vs.110%29.aspx)? – valverij
Что-то по строкам '\ d * (\. \ D *)? (- (\ d * (\. \ D *)?))?' Должно быть допустимым упрощением. Чтобы проверить все, что вам нужно было бы связать с этим регулярным выражением в группе захвата внутри другой, содержащей запятые и необязательные пробелы. –
Я бы сказал: '\ d + (?: \. \ D +)? (?: - \ d + (?: \. \ D +)?)?'. Используйте группу захвата '0' (полное совпадение). –