2015-09-25 2 views
3

У меня есть список имен проектов, которые мне нужно некоторое соответствие on.The список проектов может выглядеть примерно так:Regular Expression - получить частичную строку

suzu 
suzu-domestic 
suzu-international 
suzuran 
suzuran-international 
scorpion 
scorpion-default 
yada 
yada-yada 
etc 

Если искал проект suzu, я хотел бы иметь следующий результат из списка:

suzu 
suzu-domestic 
suzu-international 

но не ничего, содержащего suzuran. Я также хотел бы иметь следующий матч, если поиск проекта suzuran

suzuran 
suzuran-international 

но не ничего, содержащего suzu.

В C# код у меня есть что-то, что выглядит примерно так:

String searchForProject = "suzu"; 
String regStr = @"THE_REGEX_GOES_HERE"; // The regStr will be in a config file 
List<Project> projects = DataWrapper.GetAllProjects(); 
Regex regEx = new Regex(String.Format(regStr, searchForProject)); 
result = new List<Project>(); 
foreach (Project proj in projects) 
{ 
    if (regEx.IsMatch(proj.ProjectName)) 
    { 
    result.Add(proj); 
    } 
} 

Вопрос заключается в том, могу ли я иметь регулярное выражение, которое позволит мне получить матч на всех точных названий проектов, но не те, который будет возвращен startWith эквивалентом? (Сегодня у меня есть regStr = @"^({0})#", но это не удовлетворяет описанному выше сценарию, так как он дает больше ударов, чем он должен)

Я был бы признателен, если кто-то может дать мне подсказку в правильном направлении. Благодаря ! Magnus

ответ

2

Все, что вам нужно на самом деле

var regStr = @"^{0}\b"; 

^ якорь утверждает позицию в начале строки. Образец \b соответствует расположению между словом и символом не-слова, началом или концом строки. Вам не нужно сопоставлять остальную строку с .*, так как вы используете Regex.IsMatch, это избыточные накладные расходы.

C# код тест:

var projects = new List<string>() { "suzu", "suzu-domestic", "suzu-international", "suzuran", "suzuran-international", "scorpion", "scorpion-default", "yada", "yada-yada" }; 
var searchForProject = "suzu"; 
var regStr = @"^{0}\b"; // The regStr will be in a config file 

var regEx = new Regex(String.Format(regStr, searchForProject)); 
var result = new List<string>(); 
foreach (var proj in projects) 
{ 
    if (regEx.IsMatch(proj)) 
    { 
     result.Add(proj); 
    } 
} 

enter image description here

foreach может быть заменен на более короткий LINQ:

var result = projects.Where(s => regEx.IsMatch(s)).ToList(); 
+0

Вот ссылка на ссылку [** word border '\ b' **] (http://www.regular-expressions.info/wordboundaries.html) на regular-expressions.info, на всякий случай, если вы заинтересованы. Если вместо '-' вместо' '' '_', вам придется использовать что-то вроде' (?! [\ P {L} \ p {N}]) ', а' _' - символ слова. –

+1

Отлично stribizhev! Я ценю дополнительную _tutorial_ относительно LINQ и ссылку на ** границу слова **! – Metscore

+0

Что касается производительности регулярных выражений против чистого подхода LINQ: если вы объявляете регулярное выражение как поле «public static readonly» в статическом классе с помощью 'RegexOptions.Compiled', скорость будет сопоставимой, а регулярное выражение предоставит вам лучшую гибкость и контроль над вашим текстовым вводом и выводом. –

0

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

^suzu\b.* 

Working demo

Если вы хотите suzuran просто использовать:

^suzuran\b.* 
+0

'Suzu \ б *' поймает "Исузу" :-) – Amit

+0

@Amit очень умный,. Спасибо за совет. Просто обновлено –

0

Вы можете использовать "\b{0}\b.*", если вы хотите совпадение в любом месте строки (но не в середине слова), или "^{0}\b.*", если вы хотите только в начале.

См. Образец regexstorm.

0

Если вы хотите элегантное решение в одной линии с Linq и без regex, вы можете проверить это рабочее решение (демо на .NETFiddle):

using System; 
using System.Linq; 
using System.Collections.Generic; 

public class Program 
{ 
    public void Main() 
    { 
     string input = "suzu"; 
     string s = @"suzu 
suzu-domestic 
suzu-international 
suzuran 
suzuran-international 
scorpion 
scorpion-default 
yada 
yada-yada"; 

     foreach (var line in ExtractLines(s, input)) 
      Console.WriteLine(line);  
    } 

    // works if "-" is your delimiter. 
    IEnumerable<string> ExtractLines(string lines, string input) 
    { 
     return from line in lines.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) // use to split your string by line 
      let cleanLine = line.Contains("-") ? line.Split('-')[0] : line // use only the needed part 
      where cleanLine.Equals(input) // check if the output match with the input 
      select line; // return the valid line 
    } 
} 
0

С отрицательного предпросмотра:

suzu(?!.*ran).*\b 

Это также использует \ б для слова перерыв