Проще всего было бы заменить каждый %Label%
на (?<Label>.*?)
и экранировать любые другие символы.
%Artist%-%Album%-%Track%-%Title%.mp3
становится
(?<Artist>.*?)-(?<Album>.*?)-(?<Track>.*?)-(?<Title>.*?)\.mp3
Затем вы бы поместили каждый компонент в именованные группы захвата.
Dictinary<string,string> match_filename(string rule, string filename) {
Regex tag_re = new Regex(@'%(\w+)%');
string pattern = tag_re.Replace(Regex.escape(rule), @'(?<$1>.*?)');
Regex filename_re = new Regex(pattern);
Match match = filename_re.Match(filename);
Dictionary<string,string> tokens =
new Dictionary<string,string>();
for (int counter = 1; counter < match.Groups.Count; counter++)
{
string group_name = filename_re.GroupNameFromNumber(counter);
tokens.Add(group_name, m.Groups[counter].Value);
}
return tokens;
}
Но если пользователь пропустит разделители, или если разделители могут содержаться в полях, вы можете получить некоторые странные результаты. Шаблон для %Artist%%Album%
станет (?<Artist>.*?)(?<Album>.*?)
, что эквивалентно .*?.*?
. Шаблон не будет знать, где разбить.
Эту проблему можно решить, если вы знаете формат определенных полей, таких как номер дорожки. Если вместо этого вы переведете %Track%
в (?<Track>\d+)
, шаблон будет знать, что любые цифры в имени файла должны быть Track
.