2009-08-09 5 views
0

В принципе у меня есть музыкальные имена, такие как:Как совместить эти строки с регулярным выражением?

<source> <target> 

"Travis - Sing" "Travis - Sing 2001.mp3" 
"Travis - Sing" "Travis - Sing Edit.mp3" 
"Travis - Sing" "Travis - Sing New Edit.mp3" 
"Mission Impossible I" "Mission Impossible I - Main Theme.mp3" 
"Mission Impossible I" "Mission Impossible II - Main Theme.mp3" 
"Mesrine - Death Instinct" "Mesrine - Death Instinct - Le Million.mp3" 
"Mesrine - Public Enemy #1" "Mesrine - Public Enemy #1 - Theme" 
"Se7en" "Se7en Motion Picture Soundtrack - Theme.mp3" 

Скобки не включены в строки (только для демонстрации).

и я пытаюсь сопоставить «источник» с «целевыми» значениями.

Итак, имена источников у меня уже есть, но прямо сейчас я использую много синтаксического анализа строк, чтобы соответствовать двум. Как я могу добиться того же, используя Regex?

EDIT: Кажется, что есть путаница.

"Travis - Sing" моя исходная строка, и я пытаюсь сопоставить его:

"Travis - Sing (2001).mp3" 
"Travis - Sing (Edit).mp3" 
"Travis - Sing (New Edit).mp3" 

EDIT2: Удалены скобка.

+0

Я действительно не понимаю, чего вы хотите. У вас есть такая строка, как «Travis - Sing Travis - Sing (2001) .mp3» и вы хотите вытащить: источник = "Travis - Sing" target = "Travis - Sing (2001) .mp3" Или у вас есть несколько строк источника, таких как «Travis - Sing», и вы хотите совместить с кучей имен файлов? Или это что-то еще я не понимаю? –

+0

Последнее, что вы упомянули. Я думал, что это будет очевидно с моей информацией в нижней части «кода». –

ответ

1

Всегда ли между источником и целью всегда есть несколько пробелов? Если это так, то следующая будет соответствовать:

/^(.*?)\s{2,}(.*?)$/ 

Это в основном соответствует два элемента, один перед любой зазор 2+ пробельных и один за этот промежуток. (Модели захвата используют не жадный .*?, так что если есть более двух пробелов, дополнительные пробелы не будут захвачены в обоих.)

+0

Спасибо. Некоторые исходные строки не имеют пробелов. Я должен обновить сообщение. –

+0

Пространства * в * источник не имеет значения - мой вопрос состоял в том, есть ли всегда много пробелов * между * источником и целью. то есть это всегда '(источник) XX (target)' или есть случаи, когда это только одно пространство '(источник) X (target)' где X является символом пробела? – Amber

+0

Извините. я имел в виду, что это отдельные строки, я хочу сопоставить источник с целью, поэтому «Travis-Sing» - это мой источник, а строки №1, 2 и 3 - это то, к чему я хочу соответствовать, поскольку они одинаковы песня. По линии 1, 2 и 3 я имею в виду (Travis - Sing (2001) .mp3) ... и т.д. –

2

Из вашего ответа на мой комментарий Я уверен, что вы ищете для чего-то простого.

Таким образом, вы можете иметь несколько терминов поиска, разделенных символом «|». Это alternation construct.

class Program 
{ 
    private static List<string> searchList = new List<string> 
            { 
             "Travis - Sing (2001).mp3", 
             "Travis - Sing (Edit).mp3", 
             "Mission Impossible I - Main Theme.mp3", 
             "Mission Impossible II - Main Theme.mp3", 
             "doesn't match" 
            }; 

    static void Main(string[] args) 
    { 
     var matchRegex = new Regex("Travis - Sing|Mission Impossible I"); 
     var matchingStrings = searchList.Where(str => matchRegex.IsMatch(str)); 

     foreach (var str in matchingStrings) 
     { 
      Console.WriteLine(str); 
     } 
    } 
} 

EDIT Если вы хотите знать, что вы сопоставляются, вы можете добавить groups:

static void Main(string[] args) 
    { 
     var matchRegex = new Regex("(?<travis>Travis - Sing)|(?<mi>Mission Impossible I)"); 

     foreach (var str in searchList) 
     { 
      var match = matchRegex.Match(str); 
      if (match.Success) 
      { 
       if (match.Groups["travis"].Success) 
       { 
        Console.WriteLine(String.Format("{0} matches against travis", str)); 
       } 
       else if (match.Groups["mi"].Success) 
       { 
        Console.WriteLine(String.Format("{0} matches against mi", str)); 
       } 
      } 
     } 
    } 
+0

Спасибо, я думаю, что это так. У меня есть 2 вопроса. Вы включили скобки в sourcelist, а не в список поиска? Если это так, они должны выйти. Извините, мне хотелось бы разобраться в этом вопросе. 2-й вопрос есть, делает | означает отдельную запись в Regex? Если это так, я должен создать одну строку? В принципе, я хочу собрать совпадения для каждой строки источника. Так же, как source0 -> a, b, c | source1 -> d, e ... –

+0

Добавил больше информации в мой ответ. –

+0

Спасибо. Есть ли способ добавить группы в регулярное выражение без создания очень длинной отдельной строки? Так как regex.AddGroup («travis»), ... –

3

Кажется, что вы ищете все файлы, которые начинаются с определенная строка - это ответит на все ваши примеры. Это может быть легко достигнуто без регулярных выражений с помощью двух петель, или с помощью LINQ:

var matches = from source in sources 
       select new 
         { 
          Source = source, 
          Targets = from file in targets 
            where file.StartsWith(source) 
            select file 
         }; 

Вы также можете использовать регулярные выражения вместо условия StartsWith, например:

where Regex.IsMatch(file, String.Format("^{0}", source), RegexOptions.IgnoreCase) 

Это, вероятно, может быть оптимизирована во многих отношениях, но Эндрю предлагает написать длинный шаблон, который не ускоряется, когда выполняется динамично.

+0

+1 Я бы не предлагал сделать это по-своему, я бы сделал это с чем-то похожим на то, что вы делаете. Мой ответ был больше, чтобы прояснить его запросы регулярного выражения. –

+0

Спасибо, я использую это точно. Просто думал, что регулярное выражение будет быстрее, вот почему я спросил. Наверное, я должен придерживаться своего старого метода. –

1

Следующий способ является более надежным (позволяет различное количество пробелов или подменю между источником и целью). Например. у цели могут быть дополнительные пробелы между словами, но она все равно будет соответствовать.

Сначала укажите символы, которые разрешены как разделители слов в вашей строке. Затем разделите исходные и целевые строки на токены, используя разделители. Затем проверьте, не найдены ли слова в вашем источнике в качестве начальных слов.

E.g.(Java) Я использовал пробелы и дефисы в качестве разделителей

public boolean isValidMatch(String source, String target){ 
    String[] sourceTokens = source.split("[\\s\\-]+"); // split on sequence of 
    //whitespaces or dashes. Two dashes between words will still split 
    //same as one dash. 

    String[] targetTokens = target.split("[\\s\\-]+"); // split similarly 
    if(sourceTokens.length>targetTokens.length){ 
     return false; 
    } 

    for(int i=0;i<souceTokens.length;i++){ 
     if(!sourceTokens[i].equals(targetTokens[i])){ 
      return false; 
     } 
    } 
    return true; 
} 

PS: Вы можете добавить точку «» символ как разделитель, если у вас есть источник «Hello World» и целевой «Hello World.mp3»; В настоящее время это не будет соответствовать, поскольку регулярное выражение не разбивается на точку, но если вы расширите свой набор разделителей, включив точку, то это произойдет.