2015-05-23 12 views
5

Używanie funkcji regex w języku C# do dopasowywania i zwracania danych analizowanych z łańcucha zwraca niewiarygodne wyniki.Wzorzec Regex nie pasuje do niektórych tytułów programów.

Wzór używam jest następująco:

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

Poniżej zamieszczono opis przypadków testowych pary, które nie


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

powinien powrócić

  • Pokaż Nazwa (np Ellen)
  • data (np 2015.05.22)
  • Dodatkowe informacje (np Joseph Gordon Levitt [REPOST])

Alaskan Bush People S02 Wild Times Special 

powinien powrócić

  • Pokaż Imię (np Alaskan Bush People)
  • Sezon (np. 02)
  • Dodatkowe informacje (np Wild Times Special)

500 Questions S01E03 

powinien powrócić

  • Pokaż nazwy (np 500 Questions)
  • Sezon (np 01)
  • Odcinek (np. 03)

Przykłady, które pracują i powrotu odpowiednich danych

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 

co wydaje się, że wzór jest ignorowanie S i E, jeżeli nie zostanie znaleziony, a następnie za pomocą pierwszego zestaw pasujących liczb, aby wypełnić to miejsce.

Jest oczywiste, że potrzeba więcej pracy nad tym wzorem, aby pracować z powyższymi zmiennymi łańcuchami. Twoja pomoc w tej sprawie jest bardzo doceniana.

+0

'@" S (\ d {1,2}) PL (. *?)? (\ d {1,2}) (. *) | (. *?) S? (\ d {1,2}) E? (\ d {1,2}) "dlaczego dwa razy napisałeś ten sam wzór? ? –

+0

to nie jest ten sam wzór. zauważ, że jeden kończy się znakiem (. *) dla znaków końcowych, podczas gdy drugi nie. Znalazłem, że jeśli usunę (. *), Ciągi z większą liczbą znaków po numerze odcinka nie zostaną w ogóle złapane. –

+0

to, co mówię, to druga część to podzbiór pierwszej części, w której '. *' Dopasowuje zero znaków ... ?? –

Odpowiedz

5

Divide and Conquer

Starasz się analizować zbyt wiele z jednego prostego wyrażenia. To nie zadziała zbyt dobrze. Podejście w tym przypadku polega na podzieleniu problemu na mniejsze problemy i rozwiązaniu każdego z nich osobno.Następnie możemy połączyć wszystko w jeden wzór później.

Napiszmy niektóre wzorce dla danych, które chcesz wyodrębnić.

  • Sezon/epizod:

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

    użyłem \p{Pd} zamiast - celu dostosowania do każdego rodzaju deski rozdzielczej.

  • Data:

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

    Albo ...

    (?i:January|February|March|April|May|June|July|August|September|October|November|December) 
    \s*\d{1,2},\s*\d{4} 
    
  • Napisz prosty wzór dla INFORMACJE DODATKOWE:

    .*? 
    

    (tak, to dość ogólne)

  • Możemy również wykryć format pokazu tak:

    \[.*?\] 
    
  • Możesz dodać dodatkowe elementy wymagane.

Teraz możemy umieścić wszystko w jeden wzór, używając nazwy grup wyodrębnić dane:

^\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*$ 

prostu zignorować grupę info (nie jest to wykorzystywane do warunkowego w extra, tak że extra robi” t spożywać to, co powinno być częścią nazwy programu). Można uzyskać wiele informacji o numerach extra, więc po prostu połącz je, wstawiając spację między każdą częścią.

Kod próbki:

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); 
    } 
} 

a wyjście jest ...

--- 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

Przetestuję to. Ty. –

+0

Twoje dane zwracają potrzebne informacje na podstawie powyższych informacji w pytaniu. Zetknąłem się z innym, który być może mógłbyś rozwiązać (i pomogłoby mi lepiej zrozumieć, jak się grupuje) >> 'Jimmy Fallon 2015 05 22 Sting and Kevin Connolly'. Próbowałem dodać opcję dla tej daty, ale nie jestem pewien :) –

+0

Oczywiście, możesz dodać: '(? \ d {4} [] \ d {1,2} [] \ d {1,2}) 'lub' (? \ d {4} \ s \ d {1,2} \ s \ d {1,2}) ', a może nawet zmienić' (? \ d {4} \. \ d {1,2} \. \ D {1,2}) 'na' (? \ d {4} [.] \ D {1,2} [.] \ D {1,2}) "ale to ostatnia opcja akceptowałaby również "2015 05.22" - wybierasz najlepszy wariant. –

1

Spróbuj tego:

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

Dadzą temu szansę. Ty. –

+0

Ta metoda nie zwróciła prawidłowych wyników.Dziękuję za próbę;) –