представьте в виде строки “поиск и замену” использование.NET regex

Я должен сделать 2 правила "замена" - мои правила, заменяют, все открывают parens, "(" с дефисом "-" и разделяют все закрытие parens")".

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

"foobar (baz2)" стал бы

"foobar-baz2"

Я в настоящее время делаю это как это - но, моя догадка regex была бы более чистой.

myString.Replace("(", "-").Replace(")", "");
8
задан John Saunders 26 March 2010 в 20:16
поделиться

8 ответов

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

7
ответ дан 5 December 2019 в 10:40
поделиться

Нет. Это совершенно чисто.

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

1
ответ дан 5 December 2019 в 10:40
поделиться

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

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

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

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

0
ответ дан 5 December 2019 в 10:40
поделиться

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

1
ответ дан 5 December 2019 в 10:40
поделиться

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

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

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

3
ответ дан 5 December 2019 в 10:40
поделиться

Вот забавное решение проблемы на основе 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
ответ дан 5 December 2019 в 10:40
поделиться

Вы можете использовать один regex для замены обоих этих вхождений в одной строке, но это будет менее "щадящим", чем две замены строки с одним правилом.

Пример:

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

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

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

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

3
ответ дан 5 December 2019 в 10:40
поделиться

Я бы подумал, что регулярное выражение будет хрупким для такого рода вещей. Если в вашей версии .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 до 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);

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

1
ответ дан 5 December 2019 в 10:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: