2015-10-01 2 views
2

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

У меня есть набор из черного списка ключевых слов:

прием, до свидания, присоединиться к нам

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

string.Format(@"\b{0}s*\b", keyword) 

Однако я столкнулся с проблемой соответствия ключевых слов двумя словами и любым символом между ними. Вышеупомянутое регулярное выражение совпадает с «присоединяйтесь к нам», но мне также нужно сопоставить «join @ us» или «join_us».

Любая помощь была бы принята с благодарностью.

ответ

5

Я считаю, что «любой символ между ними» может вызвать у вас массу проблем. Например, давайте рассмотрим это:

Мы хотим найти «мой эльф» ... но вы, вероятно, не хотите соответствовать «себе».

В любом случае. Если это нормально, вы замените символ пробела точкой в ​​ключевом слове, используя string.Replace.

. в regex будет соответствовать любому персонажу.

Если вы новичок в регулярных выражений, проверить эту полезную шпаргалку: http://www.mikesdotnetting.com/article/46/c-regular-expressions-cheat-sheet

Чтобы решить проблему с «себя» и «мой эльф», использовать что-то более тщательно, чем . в регулярном выражении. Например, [^a-zA-Z], который будет соответствовать любым словам, кроме букв от a до z и от A до Z, или, может быть, \W, что будет соответствовать символу без слова, что означает что-либо, кроме a-zA-Z0-9_, поэтому оно эквивалентно [^a-zA-Z0-9_].

Также будьте осторожны с множественными формами, такими как города - города и все нерегулярные.

0

Если вы настроили использование плюрализации, вам необходимо использовать PluralizationService (см. this answer для получения дополнительной информации).

И, видя, что вы используете string.Format, я предполагаю, что вы зацикливаете свой массив backlist.

Так почему бы не сделать все это в аккуратном методе?

public static string GetBlacklistRegexString(string[] blacklist) 
{ 
    //It seems that this service only support engligh natively, to check later 
    var ps = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en")); 

    //Using a StringBuilder for ease of use and performance, 
    //even though it's not easy on the eye :p 
    StringBuilder sb = new StringBuilder().Append(@"\b("); 

    //We're just going to make a unique regex with all the words 
    //and their plurals in a list, so we're looping here 
    foreach (var word in blacklist) 
    { 
     //Using a dot wasn't careful indeed... Feel free to replace 
     //"\W" with anything that does it for you. It will match 
     //any non-alphanumerical character 
     var regexPlural = ps.Pluralize(word).Replace(" ", @"\W"); 
     var regexWord = word.Replace(" ", @"\W"); 

     sb.Append(regexWord).Append('|').Append(regexPlural).Append('|'); 
    } 
    sb.Remove(sb.Length - 1, 1); //removing the last '|' 
    sb.Append(@")\b"); 
    return sb.ToString(); 
} 

Использование ничего удивительного, если вы уже используете регулярные выражения в .NET:

static void Main(string[] args) 
{ 
    string[] blacklist = {"Goodbye","Welcome","join us"}; 
    string input = "Welcome, come join us at dummywebsite.com for fun and games, goodbye!"; 

    //I assume that you want it case insensitive 
    Regex blacklistRegex = new Regex(GetBlacklistRegexString(blacklist), RegexOptions.IgnoreCase); 

    foreach (Match match in blacklistRegex.Matches(input)) 
    { 
     Console.WriteLine(match); 
    } 

    Console.ReadLine(); 
} 

Мы пишутся на консоли ожидаемый результат:

  • Добро пожаловать
  • Присоединиться к нам
  • goodbye

Редактировать: все еще есть проблема (работа над ней позже), если «человек» находится в ваших ключевых словах, он будет соответствовать «мужчинам» в «женщинах» ... странно, я не получаю такого поведения на regexhero.

Редактировать 2: duh, конечно, если я не группирую слова с круглыми скобками, границы слов применяются только к первому и последнему ... Исправлено.

+1

Точки это может произойти немного слишком разрешительные и ложные срабатывания. Класс символов с выбранными символами - лучшая идея. –

+1

Ваше регулярное выражение для множественного числа не будет работать для слов, которые заканчиваются на «y», например, страны/страны. Я не очень хорошо разбираюсь в строках регулярных выражений, поэтому у меня нет предложения о том, как это исправить. –

+0

Слишком быстро на исправление действительно будет двойная проверка. – Kilazur

0

Вы могли бы попробовать что-то вроде этого (я оставил только {0} часть регулярного выражения):

var relevantChars = new char[]{',', '@'}; // add here anything you like 
string.Format(@"{0}", keyword.Replace(" ", "(" + string.Join("|", relevantChars) + ")")); 
+0

Решите проблему с символом пробела, все еще нужно иметь дело с множественными значениями. – Kilazur

Смежные вопросы