В .NET вы можете использовать регулярные выражения с зазорами бесконечной ширины (это также поддерживается в последних средах JavaScript с ECMAScript 2018, если вам нужно перенести туда то же решение).Регулярное выражение будет выглядеть так:
(?<=^(?:[-+]?\d+#(?:[-+]?\d*\.?\d+|~),\s)*)[-+]?\d+#(?:[-+]?\d*\.?\d+|~)(?=(?:,\s[-+]?\d+#(?:[-+]?\d*\.?\d+|~))*$)
См. онлайн-демонстрацию регулярных выражений
В коде проще построить шаблон из переменной:
var block = @"[-+]?\d+#(?:[-+]?\d*\.?\d+|~)"; // Block/unit pattern
var pattern = $@"(?<=^(?:{block},\s)*){block}(?=(?:,\s{block})*$)";
var results1 = Regex.Matches("3#0.01, 2#0.5, 1#-10, -2#~", pattern)
.Cast<Match>().Select(x => x.Value);
if (results1.Count() > 0)
Console.WriteLine(string.Join(", ", results1));
var results2 = Regex.Matches("MISTAKE3#0.01, 2#0.5, 1#-10, -2#~AND_HERE_MISTAKE_TOO", pattern)
.Cast<Match>().Select(x => x.Value);
if (results2.Count() > 0)
Console.WriteLine(string.Join(", ", results2));
См. Демонстрационную версию C # онлайн .Выходные данные (соответствует только правая строка):
3#0.01, 2#0.5, 1#-10, -2#~
Объяснение шаблона
(?<=^(?:{block},\s)*)
- положительный вид сзади, который соответствует только местоположению, непосредственно предшествующему0+ вхождений шаблона {block}
в начале строки, за которым следуют ,
и 1 пробел {block}
- ваш шаблон блока / единицы соответствует (?=(?:,\s{block})*$)
- положительный прогноз, соответствующий местоположению, за которым сразу следует 0+ вхождений ,
, пробела и шаблона {block}
до конца строки.