Regex для инкапсуляции любых несопоставленных разделов - PullRequest
0 голосов
/ 22 апреля 2019

Используя пример фразы:

Всем мужчинам нравится виджеты , но некоторым мужчинам нравится виджеты больше, чем другим

Пример содержит два использования слова widgets . Что я пытаюсь сделать, это сопоставить биты снаружи. Обратите внимание, что хотя виджеты - это одно слово, я ищу решение для регулярных выражений, которое также будет работать с несколькими словами.

Учитывая приведенный выше пример, вывод будет содержать 3 совпадения:

  1. Всем мужчинам нравится
  2. но некоторым мужчинам нравится
  3. больше, чем другие

Пока у меня есть следующее регулярное выражение, которое работает только частично:

@"(?!widgets\b)\b\w+"

Ограничения заключаются в том, что он не может справиться с несколькими словосочетаниями - он также соответствует каждому отрицательному слову, а не всей последовательности слов, которые предшествуют / преуспевают, поэтому «все», «мужчины» и «как» вместо «все» мужчинам нравится ".

У меня есть другое решение, которое включает в себя более простое регулярное выражение и некоторые дополнительные преобразования и изменения в коде c #, но это не то решение, которым я доволен:

string EmboldenString(string text, string termToExclude)
{
    var pattern = $@" ?{termToExclude} ?";

    var tagStart = "<b>";
    var tagEnd = "</b>";

    var result = Regex.Replace($"{tagStart}{text}{tagEnd}", pattern, (match) =>
    {
        return $"{tagEnd}{match}{tagStart}";
    });

    var emptyTag = tagStart + tagEnd;

    if (result.StartsWith(emptyTag))
        result = result.TrimStart(emptyTag.ToCharArray());

    if (result.EndsWith(emptyTag))
        result = result.TrimEnd(emptyTag.ToCharArray());

    return result;
}

Как видно из кода выше, цель состоит в добавлении тегов ко всем несовпадающим битам.

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

Ответы [ 2 ]

1 голос
/ 22 апреля 2019

Вы можете использовать Regex.Split, а затем обернуть каждый нечетный элемент в результирующем массиве / списке любыми тегами, которые вам нравятся:

var s = "All men like widgets but some men like widgets more than others";
var chunks = Regex.Split(s, @"(\s*\bwidgets\b\s*)");
var result = string.Concat(chunks.Select((i, index) => index % 2 == 0 ? $"<b>{i}</b>" : i));
Console.WriteLine(result);
// => <b>All men like</b> widgets <b>but some men like</b> widgets <b>more than others</b>

См. Демоверсию C # .

Шаблон (\s*\bwidgets\b\s*) сопоставляет и фиксирует в группе 1 0+ пробелы, целое слово widgets и снова 0+ пробелы. Эти совпадения хранятся в результирующем массиве, потому что они фиксируются. Каждый нечетный элемент является несоответствующей подстрокой.

Если вы не хотите оборачивать пустые несоответствия тегами, добавьте дополнительный !string.IsNullOrWhiteSpace(i) флажок:

var chunks = Regex.Split(s, @"(\s*\bwidgets\b\s*)");
var result = string.Concat(
    chunks.Select((i, index) => 
        index % 2 == 0 && !string.IsNullOrWhiteSpace(i) ? 
            $"<b>{i}</b>" : i));

См. эту демонстрацию C # .

1 голос
/ 22 апреля 2019

Как сказал Ахмед, вы должны использовать Regex.Spilt()

Вот пример для вашего варианта использования

var op = Regex.Split("All men like widgets but some men like widgets more than others", @"widgets");

выход

//All men like
//but some men like
//more than others

Обновление

Вы можете использовать ниже код

string op = GetTagsAroud("All men like widgets but some men like widgets more than others", @"widgets");

Метод

static string GetTagsAroud(string input, string splitText)
{
    var matches = Regex.Split(input, splitText);
    StringBuilder output = new StringBuilder();
    foreach (string match in matches)
    {
        output.Append("<b>");
        output.Append(match.Trim());
        output.Append("</b>");
    }
    return output.ToString();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...