Corrispondenza di modelli e valori segnaposto
-
05-07-2019 - |
Domanda
Sto scrivendo un'applicazione che utilizza le regole di ridenominazione per rinominare un elenco di file in base alle informazioni fornite dall'utente.I file potrebbero avere nomi incoerenti all'inizio oppure i nomi dei file potrebbero essere coerenti.L'utente seleziona un elenco di file e inserisce le informazioni sui file (per gli MP3, sarebbero Artista, Titolo, Album, ecc.).Utilizzando una regola di ridenominazione (esempio seguente), il programma utilizza le informazioni immesse dall'utente per rinominare i file di conseguenza.
Tuttavia, se tutti o alcuni file hanno nomi coerenti, vorrei consentire al programma di "indovinare" le informazioni sul file.Questo è il problema che sto riscontrando.Qual è il modo migliore per farlo?
Nomi file di esempio:
Kraftwerk-Kraftwerk-01-RuckZuck.mp3
Kraftwerk-Autobahn-01-Autobahn.mp3
Kraftwerk-Computer World-03-Numbers.mp3
Rinomina regola:
%Artist%-%Album%-%Track%-%Title%.mp3
Il programma dovrebbe dedurre correttamente l'artista, il numero della traccia, il titolo e il nome dell'album.
Ancora una volta, qual è il modo migliore per farlo?Stavo pensando alle espressioni regolari, ma sono un po' confuso.
Soluzione
La cosa più semplice sarebbe sostituirli tutti %Label%
con (?<Label>.*?)
, e sfuggi a qualsiasi altro personaggio.
%Artist%-%Album%-%Track%-%Title%.mp3
diventa
(?<Artist>.*?)-(?<Album>.*?)-(?<Track>.*?)-(?<Title>.*?)\.mp3
Dovresti quindi inserire ciascun componente in gruppi di acquisizione denominati.
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;
}
Ma se l'utente tralascia i delimitatori o se i delimitatori potrebbero essere contenuti all'interno dei campi, potresti ottenere risultati strani.Il modello sarebbe per %Artist%%Album%
potrebbe diventare (?<Artist>.*?)(?<Album>.*?)
che è equivalente a .*?.*?
.Lo schema non saprebbe dove dividersi.
Questo potrebbe essere risolto se conosci il formato di alcuni campi, come il numero della traccia.Se traduci %Track%
A (?<Track>\d+)
invece, il modello saprebbe che qualsiasi cifra nel nome del file deve essere il Track
.
Altri suggerimenti
Non la risposta alla domanda che hai posto, ma una tag ID3 potrebbe essere un modo migliore per farlo quando si utilizzano MP3. Un rapido Google ha prodotto: Libreria C # ID3 .
Per quanto riguarda indovinare quali posizioni delle stringhe contengono l'artista, l'album e il titolo della canzone ... la prima cosa che mi viene in mente è che se hai una buona selezione con cui lavorare, diciamo diversi album, potresti prima vedere quale posizione ripete di più, che sarebbe l'artista, che ripete il secondo più (album) e che ripete il meno (titolo del brano).
Altrimenti, sembra difficile indovinare basandosi solo su alcune stringhe nel nome del file ... potresti chiedere all'utente di inserire anche un'espressione corrispondente per il nome del file che descrive l'ordine dei campi?
I nomi dei file nel tuo esempio mi sembrano abbastanza coerenti. Puoi semplicemente fare string.Split () e aggiungere ogni elemento dell'array risultante alle sue informazioni tag corrispondenti.
Indovinare in quale posizione si trovano le informazioni sui tag che implicherebbero tonnellate di euristica.
Btw. le cartelle che contengono file di brani di solito hanno anche un modello nel loro nome, ad esempio
1998 - Seven
1999 - Periscope
2000 - CO2
Il formato qui è% Year% -% AlbumName%, che potrebbe aiutarti a identificare quale elemento nel nome del file è l'album.
Per chiarire, DO ho uno schema per abbinare i nomi dei file.
Non conosco il nome file o il modello in anticipo, è tutto runtime.
Modello:
%Artist%-%Album%-%Track%-%Title%.mp3
I nomi dei file:
Kraftwerk-Kraftwerk-01-RuckZuck.mp3 Kraftwerk-Autobahn-01-Autobahn.mp3 Kraftwerk-Computer World-03-Numbers.mp3
Risultato atteso:
Artist Album Track Title Kraftwerk Kraftwerk 01 RuckZuck Kraftwerk Autobahn 01 Autobahn Kraftwerk Computer World 01 Numbers
Ancora una volta, il formato e i nomi dei file non sono sempre gli stessi.
Ho scritto un renamer di file della riga di comando --- RenameWand --- che fa il tipo di pattern matching che stai descrivendo. È in Java però, ma penso che parte del codice sorgente e della documentazione sull'utilizzo possano essere di tuo interesse. Un semplice esempio di cosa può fare il programma:
Pattern sorgente (specificato dall'utente):
<artist>-<album>-<track>-<title>.mp3
Target Pattern (specificato dall'utente):
<title.upper>-<3|track+10>-<album.lower>-<artist>.mp3
Nome file originale:
Kraftwerk-Computer World-03-Numbers.mp3
Nome file rinominato:
NUMBERS-013-computer world-Kraftwerk.mp3