Сопоставление с шаблоном и значения-заполнители
-
05-07-2019 - |
Вопрос
Я пишу приложение, которое использует правила переименования для переименования списка файлов на основе информации, предоставленной пользователем.Файлы могут иметь несогласованные имена с самого начала, или имена файлов могут быть согласованными.Пользователь выбирает список файлов и вводит информацию о файлах (для MP3-файлов это может быть Исполнитель, Название, Альбом и т.д.).Используя правило переименования (пример ниже), программа использует введенную пользователем информацию для соответствующего переименования файлов.
Однако, если все или некоторые файлы названы последовательно, я хотел бы разрешить программе "угадывать" информацию о файле.Вот в чем проблема, с которой я столкнулся.Каков наилучший способ сделать это?
Примеры имен файлов:
Kraftwerk-Kraftwerk-01-RuckZuck.mp3
Kraftwerk-Autobahn-01-Autobahn.mp3
Kraftwerk-Computer World-03-Numbers.mp3
Правило переименования:
%Artist%-%Album%-%Track%-%Title%.mp3
Программа должна правильно указать Исполнителя, номер трека, Название и название альбома.
Опять же, как лучше всего это сделать?Я думал о регулярных выражениях, но я немного запутался.
Решение
Проще всего было бы заменить каждый %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
.
Другие советы
Не ответ на заданный вами вопрос, а тег ID3 библиотека чтения может быть лучший способ сделать это, когда вы используете MP3. Google быстро нашел: Библиотека C # ID3 .
Что касается угадывания того, какие позиции строк содержат исполнителя, альбом и название песни ... Первое, о чем я могу подумать, это то, что если у вас есть хороший выбор для работы, скажем, с несколькими альбомами, вы можете сначала увидеть, какая позиция повторяется больше всего, который будет исполнителем, который повторяет второй наиболее (альбом) и который повторяет меньше всего (название песни). Р>
В противном случае кажется трудным сделать предположение, основываясь только на нескольких строках в имени файла ... не могли бы вы попросить пользователя также ввести соответствующее выражение для имени файла, которое описывает порядок полей? р>
Имена файлов в вашем примере кажутся мне довольно последовательными.Вы можете просто выполнить string .Split() и добавить каждый элемент результирующего массива к соответствующей информации тега.
Угадывание того, в какой позиции находится информация о теге, потребовало бы ТОННЫ эвристики.
Кстати.папки, содержащие файлы песен, обычно также имеют некоторый шаблон в своем названии, например.
1998 - Семь
1999 - Перископ
2000 - CO2
Формат здесь такой: %Year% - %albumName%, это может помочь вам определить, какой элемент в имени файла является альбомом.
Чтобы внести ясность, я ДЕЛАЙ создайте шаблон для сопоставления имен файлов.
Я не знаю имя файла или шаблон заранее, все это происходит во время выполнения.
Узор:
%Artist%-%Album%-%Track%-%Title%.mp3
Имена файлов:
Kraftwerk-Kraftwerk-01-RuckZuck.mp3 Kraftwerk-Autobahn-01-Autobahn.mp3 Kraftwerk-Computer World-03-Numbers.mp3
Ожидаемый результат:
Artist Album Track Title Kraftwerk Kraftwerk 01 RuckZuck Kraftwerk Autobahn 01 Autobahn Kraftwerk Computer World 01 Numbers
Опять же, формат и имена файлов не всегда совпадают.
Я написал переименователь файла командной строки --- RenameWand --- который выполняет соответствия шаблону вы описываете. Хотя это на Java, но я думаю, что некоторые из исходного кода и документации по использованию могут вас заинтересовать. Простой пример того, что может сделать программа:
Исходный шаблон (определяется пользователем):
<artist>-<album>-<track>-<title>.mp3
Шаблон цели (определяется пользователем):
<title.upper>-<3|track+10>-<album.lower>-<artist>.mp3
Исходное имя файла:
Kraftwerk-Computer World-03-Numbers.mp3
Переименовано имя файла:
NUMBERS-013-computer world-Kraftwerk.mp3