Быстрая деконструкция Regex
Описание
У меня есть результат Regex-а Match match
, группы которой я хочу разобрать на части вот так:
- первую группу пропустить,
- вторую группу присвоить к переменной
instruction
, - все остальные присвоить к переменной
args
.
В JavaScript это выглядело бы так:
const match = /example/.exec(`example`);
if (match === null) return;
const [, instruction, ...args] = match;
Хотел бы сделать такую же деконструкцию и в C#:
Match match = new Regex(@"example").Match("example");
if (!match.Success) return;
(_, Group instruction, Group[] ..args) = match.Groups;
Вопрос
Слышал, что в последних версиях C# появилось много синтаксического сахара и даже оператор ..
. Попробовал, везде получил ошибку.
Как все-таки выполнить эту деконструкцию?
Ответы (2 шт):
Можно использовать pattern matching, а именно List patterns.
Однако, это выглядит несколько неуклюже из-за того, что это нужно использовать в условном операторе if
/switch
.
var groups = new string[] { "a", "b", "c", "d" };
if (groups is [_, var ins, .. var arg])
{
Console.WriteLine(ins); // b
Console.WriteLine(string.Join(",", arg)); // c,d
}
Можно просто использовать доступ по индексу и LINQ:
var ins2 = groups[1];
var arg2 = groups.Skip(2); //.ToArray();
Можно использовать именованные группы. Группа указывается через (?<НазваниеГруппы>метасимволы)
, пример (?<FirstWord>\\w+)\\s(?<SecondWord>\\w+)
— непрерывное количество алфавитно-цифровых символов (не менее одного), потом идёт пробел, потом тоже любое непрерывное количество алфавитно-цифровых символов (не менее одного). Обращение к группе происходит через индексатор, принимающий строковый параметр у GroupCollection
(свойство Groups
). Пример кода:
var regex = new Regex("(?<FirstWord>\\w+)\\s(?<SecondWord>\\w+)");
var match = regex.Match(@"ПервоеСлово ВтороеСлово");
if (match.Success)
{
var firstWord = match.Groups["FirstWord"].Value;
var secondWord = match.Groups["SecondWord"].Value;
Console.WriteLine(firstWord);
Console.WriteLine(secondWord);
}
else
{
Console.WriteLine("Неудача");
}
Можно ещё даже так, из-за перегруженной версии метода ToString
у класса Capture
:
var regex = new Regex("(?<FirstWord>\\w+)\\s(?<SecondWord>\\w+)");
var match = regex.Match(@"ПервоеСлово ВтороеСлово");
if (match.Success)
{
Console.WriteLine(match.Groups["FirstWord"]);
Console.WriteLine(match.Groups["SecondWord"]);
}
По поводу деконструирования объекта, у класса GroupCollection
не определён метод Deconstruct
, поэтому нет возможности сделать то, что вы хотите. Если хочется сделать какой-то кастом, то это будет костыль и он будет выглядеть вот так:
static void Main(string[] args)
{
var regex = new Regex("(?<FirstWord>\\w+)\\s(?<SecondWord>\\w+)");
var match = regex.Match(@"ПервоеСлово ВтороеСлово");
if (match.Success)
{
var (_, secondWord) = Deconstruct(match.Groups);
Console.WriteLine(secondWord.Value);
}
else
{
Console.WriteLine("Неудача");
}
}
private static (Capture, Capture) Deconstruct(GroupCollection groups)
{
return (groups[1], groups[2]);
}