строка "искать и заменить" с использованием регулярных выражений .NET - PullRequest
8 голосов
/ 26 марта 2010

Мне нужно сделать 2 правила «заменить» - мои правила таковы: заменить все открытые символы "(" с дефисом "-" и удалить все закрывающие символы ")".

Так, например, это:

"foobar (baz2)" станет

"Foobar-baz2"

В настоящее время я делаю это так, но мое предположение будет чище.

myString.Replace("(", "-").Replace(")", "");

Ответы [ 8 ]

7 голосов
/ 26 марта 2010

Я бы не пошел в RegEx за этим - то, что вы делаете, просто правильно Это ясно и понятно ... регулярные выражения вряд ли сделают это проще или понятнее. Вам все равно нужно сделать два звонка на Replace, потому что ваши замены различны для каждого случая.

3 голосов
/ 26 марта 2010

Вы МОЖЕТЕ использовать одно регулярное выражение для замены обоих этих вхождений в одной строке, но это будет менее «прощающим», чем две замены одной строки правила.

Пример:

Код, который будет использоваться для регулярных выражений, будет:

Regex.Replace(myString, @"([^\(]*?)\(([^\)]*?)\)", "$1-$2");

Это бы хорошо работало ТОЧНО для приведенного вами примера. Если бы было малейшее изменение в том, где и сколько символов '(' и ')', регулярное выражение было бы нарушено. Затем вы можете исправить это с помощью большего количества регулярных выражений, но от этого все станет только уродливее.

Regex - отличный выбор для более жестких приложений.

3 голосов
/ 26 марта 2010

Джейми Завински внезапно приходит мне в голову:

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

Так что я тоже думаю, что Л.Бушкин прав в этом случае. Ваше решение работает и доступно для чтения.

1 голос
/ 26 марта 2010

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

public static class StringExtensions
{
    public static string ReplaceMany(this string s, Dictionary<string, string> replacements)
    {
        var sb = new StringBuilder(s);
        foreach (var replacement in replacements)
        {
            sb = sb.Replace(replacement.Key, replacement.Value);
        }
        return sb.ToString();
    }
}

Так что теперь вы создаете свой словарь замен ...

var replacements = new Dictionary<string, string> { {"(", "-"}, {")", ""} };

И позвоните ReplaceMany:

var result = "foobar(baz2)".ReplaceMany(replacements); // result = foobar-baz2

Если вы действительно хотите показать свое намерение, вы можете использовать псевдоним от Dictionary<string,string> до StringReplacements:

//At the top
using StringReplacements = System.Collections.Generic.Dictionary<string,string>;

//In your function
var replacements = new StringReplacements() { {"(", "-"}, {")", ""} };
var result = "foobar(baz2)".ReplaceMany(replacements);

Mightбудьте излишни только для двух замен, но если у вас есть много, чтобы сделать это будет чище, чем .Replace().Replace().Replace().Replace()....

1 голос
/ 26 марта 2010

Я бы сказал, используйте то, что у вас есть - это более легко читается / поддерживается. Регулярные выражения очень мощные, но иногда и очень запутанные. Для чего-то такого простого, я бы даже сказал, не используйте регулярные выражения.

1 голос
/ 26 марта 2010

Неа. Это идеально чисто.

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

0 голосов
/ 27 марта 2010

Вот забавное решение проблемы на основе LINQ. Возможно, это не лучший вариант, но в любом случае он интересен:

public string SearchAndReplace(string input)
{ 
   var openParen = '(';
   var closeParen = ')';
   var hyphen = '-';
   var newChars = input
        .Where(c => c != closeParen)
        .Select(c => c == openParen ? hyphen : c);
   return new string(newChars.ToArray());
}

2 интересных замечания об этой реализации:

  • Не требует сложного регулярного выражения, поэтому вы получаете лучшую производительность и легче техническое обслуживание.
  • В отличие от реализаций string.Replace, этот метод выделяет ровно 1 строку.

Неплохо!

0 голосов
/ 26 марта 2010

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

string input = "foobar(baz2)";
string pattern = "([()])";
string result = Regex.Replace(input, pattern, m => m.Value == "(" ? "-" : "");
Console.WriteLine(result);

Идея состоит в том, чтобы взять скобки в группе. Я использовал [()], который является классом символов, который будет соответствовать тому, что мы ищем. Обратите внимание, что внутри класса персонажа их не нужно экранировать. С другой стороны, шаблон мог быть @"(\(|\))", в этом случае экранирование необходимо.

Далее, метод Replace использует MatchEvaluator, и мы проверяем, является ли зафиксированное значение открытием ( или нет. Если это так, возвращается -. Если мы не знаем, основываясь на нашем ограниченном паттерне, что это должно быть закрывающее значение ), и мы возвращаем пустую строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...