2015-05-23 10 views
5

L'uso di repressione in C# per abbinare e restituire dati analizzati da una stringa restituisce risultati inaffidabili.Il pattern Regex non corrisponde a determinati titoli di show

Il modello che sto usando è la seguente:

Regex r=new Regex( 
     @"(.*?)S?(\d{1,2})E?(\d{1,2})(.*)|(.*?)S?(\d{1,2})E?(\d{1,2})", 
     RegexOptions.IgnoreCase 
); 

seguito sono un caso paio di test che falliscono


Ellen 2015.05.22 Joseph Gordon Levitt [REPOST] 
The Soup 2015.05.22 [mp4] 
Big Brother UK Live From The House (May 22, 2015) 

dovrebbe tornare

  • Mostra nome (ad esempio, Ellen)
  • Data (ad esempio, 2015.05.22)
  • Extra Info (per esempio, Joseph Gordon Levitt [REPOST])

Alaskan Bush People S02 Wild Times Special 

dovrebbe tornare

  • Mostra nome (ad esempio, Alaskan Bush People)
  • Stagione (ad esempio, 02)
  • Extra Info (per esempio, Wild Times Special)

500 Questions S01E03 

dovrebbe tornare

  • Mostra nome (ad esempio, 500 Questions)
  • Stagione (ad esempio, 01)
  • Episodio (ad esempio, 03)

esempi che funzionano e restituiscono dati corretti

Boyster S01E13 – E14 
Mysteries at the Museum S08E08 
Mysteries at the National Parks S01E07 – E08 
The Last Days Of… S01E06 
Born Naughty? S01E02 
Have I Got News For You S49E07 

Che sembra, è che il modello sta ignorando la S e la E se non lo trova, e quindi utilizzando il primo set di numeri corrispondenti per riempire lo slot.

È chiaro che è necessario più lavoro su questo modello per lavorare con le stringhe di cui sopra. La tua assistenza in questa materia è molto apprezzata.

+0

'@" S (\ d {1,2}) E (*.?)? (\ d {1,2}) (. *) | (. *?) S? (\ d {1,2}) E? (\ d {1,2}) "' perché hai scritto lo stesso schema due volte ? –

+0

non è lo stesso modello. si noti che uno finisce con (. *) per ogni carattere finale, mentre l'altro no. Ho scoperto che se ho rimosso il (. *), Le stringhe con più caratteri dopo il numero dell'episodio non venivano catturate affatto. –

+0

quello che sto dicendo è che la seconda parte è un sottoinsieme della prima parte dove '. *' Corrisponde a zero caratteri .. ?? –

risposta

5

divide et impera

Stai cercando di analizzare troppo con una semplice espressione. Non funzionerà molto bene. L'approccio migliore in questo caso è quello di dividere il problema in problemi più piccoli e risolverli separatamente.Quindi, possiamo combinare tutto in un modello in un secondo momento.

Scriviamo alcuni modelli per i dati che vuoi estrarre.

  • Stagione/episodio:

    S\d+(?:E\d+(?:\s*\p{Pd}\s*E\d+)?)? 
    

    ho usato \p{Pd} invece di - per accogliere qualsiasi tipo cruscotto.

  • Data:

    \d{4}\.\d{1,2}\.\d{1,2} 
    

    Oppure ...

    (?i:January|February|March|April|May|June|July|August|September|October|November|December) 
    \s*\d{1,2},\s*\d{4} 
    
  • Scrivi un modello semplice per info in più:

    .*? 
    

    (sì, è piuttosto generica)

  • Possiamo rilevare anche il formato di spettacolo come questo:

    \[.*?\] 
    
  • È possibile aggiungere parti aggiuntive come richiesto.

Ora, siamo in grado di mettere tutto in un unico modello, utilizzando i nomi dei gruppi per estrarre i dati:

^\s* 
(?<name>.*?) 
(?<info> \s+ (?: 
    (?<episode>S\d+(?:E\d+(?:\s*\p{Pd}\s*E\d+)?)?) 
    | 
    (?<date>\d{4}\.\d{1,2}\.\d{1,2}) 
    | 
    \(?(?<date>(?i:January|February|March|April|May|June|July|August|September|October|November|December)\s*\d{1,2},\s*\d{4})\)? 
    | 
    \[(?<format>.*?)\] 
    | 
    (?<extra>(?(info)|(?!)).*?) 
))* 
\s*$ 

semplicemente ignorare il gruppo info (è utilizzato per la condizionale in extra, in modo che extra doesn' t consumare ciò che dovrebbe essere parte del nome dello spettacolo). E puoi ottenere più informazioni extra, quindi concatenarle semplicemente, mettendo uno spazio tra ogni parte.

codice di esempio:

var inputData = new[] 
{ 
    "Boyster S01E13 – E14", 
    "Mysteries at the Museum S08E08", 
    "Mysteries at the National Parks S01E07 – E08", 
    "The Last Days Of… S01E06", 
    "Born Naughty? S01E02", 
    "Have I Got News For You S49E07", 
    "Ellen 2015.05.22 Joseph Gordon Levitt [REPOST]", 
    "The Soup 2015.05.22 [mp4]", 
    "Big Brother UK Live From The House (May 22, 2015)", 
    "Alaskan Bush People S02 Wild Times Special", 
    "500 Questions S01E03" 
}; 

var re = new Regex(@" 
    ^\s* 
    (?<name>.*?) 
    (?<info> \s+ (?: 
     (?<episode>S\d+(?:E\d+(?:\s*\p{Pd}\s*E\d+)?)?) 
     | 
     (?<date>\d{4}\.\d{1,2}\.\d{1,2}) 
     | 
     \(?(?<date>(?i:January|February|March|April|May|June|July|August|September|October|November|December)\s*\d{1,2},\s*\d{4})\)? 
     | 
     \[(?<format>.*?)\] 
     | 
     (?<extra>(?(info)|(?!)).*?) 
    ))* 
    \s*$ 
", RegexOptions.IgnorePatternWhitespace); 

foreach (var input in inputData) 
{ 
    Console.WriteLine(); 
    Console.WriteLine("--- {0} ---", input); 

    var match = re.Match(input); 
    if (!match.Success) 
    { 
     Console.WriteLine("FAIL"); 
     continue; 
    } 

    foreach (var groupName in re.GetGroupNames()) 
    { 
     if (groupName == "0" || groupName == "info") 
      continue; 

     var group = match.Groups[groupName]; 
     if (!group.Success) 
      continue; 

     foreach (Capture capture in group.Captures) 
      Console.WriteLine("{0}: '{1}'", groupName, capture.Value); 
    } 
} 

E l'uscita di questo è ...

--- Boyster S01E13 - E14 --- 
name: 'Boyster' 
episode: 'S01E13 - E14' 

--- Mysteries at the Museum S08E08 --- 
name: 'Mysteries at the Museum' 
episode: 'S08E08' 

--- Mysteries at the National Parks S01E07 - E08 --- 
name: 'Mysteries at the National Parks' 
episode: 'S01E07 - E08' 

--- The Last Days Ofâ?¦ S01E06 --- 
name: 'The Last Days Ofâ?¦' 
episode: 'S01E06' 

--- Born Naughty? S01E02 --- 
name: 'Born Naughty?' 
episode: 'S01E02' 

--- Have I Got News For You S49E07 --- 
name: 'Have I Got News For You' 
episode: 'S49E07' 

--- Ellen 2015.05.22 Joseph Gordon Levitt [REPOST] --- 
name: 'Ellen' 
date: '2015.05.22' 
format: 'REPOST' 
extra: 'Joseph' 
extra: 'Gordon' 
extra: 'Levitt' 

--- The Soup 2015.05.22 [mp4] --- 
name: 'The Soup' 
date: '2015.05.22' 
format: 'mp4' 

--- Big Brother UK Live From The House (May 22, 2015) --- 
name: 'Big Brother UK Live From The House' 
date: 'May 22, 2015' 

--- Alaskan Bush People S02 Wild Times Special --- 
name: 'Alaskan Bush People' 
episode: 'S02' 
extra: 'Wild' 
extra: 'Times' 
extra: 'Special' 

--- 500 Questions S01E03 --- 
name: '500 Questions' 
episode: 'S01E03' 
+0

verificherà questo. Ty. –

+0

Tuo è tornato quello che mi serviva in base alle informazioni di cui sopra nella domanda. Ne ho incontrato un altro che forse potresti risolvere (e mi aiuterebbe a capire meglio il raggruppamento) >> 'Jimmy Fallon 2015 05 22 Sting e Kevin Connolly'. Ho provato ad aggiungere un'opzione per questa data, ma non sono sicuro :) –

+0

Certo, potresti semplicemente aggiungere: '(? \ d {4} [] \ d {1,2} [] \ d {1,2}) 'o' (? \ d {4} \ s \ d {1,2} \ s \ d {1,2}) ', o forse anche cambiare' (? \ d {4} \. \ d {1,2} \. \ D {1,2}) 'a' (? \ d {4} [.] \ D {1,2} [.] \ D {1,2}) 'ma quello l'ultima opzione accetterebbe '2015 05.22' anche tu - scegli la variante migliore. –

1

Prova questa:

(?<name>.*?)(?:S(?<season>\d{1,2}))?(?:E(?<episode>\d{1,2}))?(?<date>\d{4}\.\d{2}\.\d{2})(?<extra>.*)? 
+0

Darà uno scatto. Ty. –

+0

Questo metodo non ha restituito risultati corretti.Grazie per il tentativo;) –