Подтвердить что ты не робот

Удалить текст между разделителями в строке (с использованием регулярного выражения?)

Рассмотрим требование найти совпадающую пару наборов символов и удалить любые символы между ними, а также те символы/разделители.

Вот наборы разделителей:

 []    square brackets
 ()    parentheses
 ""    double quotes
 ''    single quotes

Ниже приведены примеры строк, которые должны соответствовать:

 Given:                       Results In:
-------------------------------------------
 Hello "some" World           Hello World
 Give [Me Some] Purple        Give Purple
 Have Fifteen (Lunch Today)   Have Fifteen
 Have 'a good'day             Have day

И некоторые примеры строк, которые не должны совпадать:

 Does Not Match:
------------------
 Hello "world
 Brown]co[w
 Cheese'factory

Если данная строка не содержит соответствующий набор разделителей, она не изменяется. Входная строка может содержать много совпадающих пар разделителей. Если набор из 2 разделителей перекрывается (т.е. he[llo "worl]d"), это будет краевой случай, который мы можем здесь игнорировать.

Алгоритм будет выглядеть примерно так:

string myInput = "Give [Me Some] Purple (And More) Elephants";
string pattern; //some pattern
string output = Regex.Replace(myInput, pattern, string.Empty);

Вопрос: Как бы вы это сделали с С#? Я склоняюсь к регулярному выражению.

Бонус: Есть ли простые способы сопоставления этих разделителей начала и конца в константах или в некотором списке? Решение, которое я ищу, было бы легко изменить разделители, если бизнес-аналитики придумают новые наборы разделителей.

4b9b3361

Ответ 1

Простым регулярным выражением будет:

string input = "Give [Me Some] Purple (And More) Elephants";
string regex = "(\\[.*\\])|(\".*\")|('.*')|(\\(.*\\))";
string output = Regex.Replace(input, regex, "");

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

('.*')  // example of the single quote check

Затем каждая часть регулярного выражения объединяется с OR (в regex), как в моем первоначальном примере. Как только вы построите строку регулярных выражений, просто запустите ее один раз. Ключ состоит в том, чтобы получить регулярное выражение в одну проверку, потому что выполнение множества регулярных выражений на одном элементе, а затем повторение множества элементов, вероятно, приведет к значительному снижению производительности.

В моем первом примере, который заменил бы следующую строку:

string input = "Give [Me Some] Purple (And More) Elephants";
string regex = "Your built up regex here";
string sOutput = Regex.Replace(input, regex, "");

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

Ответ 2

Простым способом было бы это сделать:

string RemoveBetween(string s, char begin, char end)
{
    Regex regex = new Regex(string.Format("\\{0}.*?\\{1}", begin, end));
    return regex.Replace(s, string.Empty);
}

string s = "Give [Me Some] Purple (And More) \\Elephants/ and .hats^";
s = RemoveBetween(s, '(', ')');
s = RemoveBetween(s, '[', ']');
s = RemoveBetween(s, '\\', '/');
s = RemoveBetween(s, '.', '^');

Изменение оператора return на следующее позволит избежать дублирования пустых пространств:

return new Regex(" +").Replace(regex.Replace(s, string.Empty), " ");

Конечным результатом для этого будет:

"Give Purple and "

Disclamer: одно регулярное выражение, вероятно, будет быстрее, чем это.

Ответ 3

Мне нужно добавить старую пословицу: "У вас есть проблема, и вы хотите использовать регулярные выражения. Теперь у вас есть две проблемы".

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

[.]*(\(|\[|\"|').*(\]|\)|\"|')[.]*

Скобки, скобки, двойные кавычки экранируются, а одиночная кавычка может быть оставлена ​​одна.

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

Открытая фраза-разделитель (\(|\[|\"|') У этого есть соответствующая заключительная фраза. Чтобы сделать это еще более расширяемым в будущем, вы можете удалить фактические разделители и содержать их в файле конфигурации, базе данных или там, где вы можете выбрать.

Ответ 4

Основываясь на регулярном выражении Брайана Менарга я сделал метод расширения, который также будет работать для вложенных заметок, таких как "[Test 1 [[Test2] Test3]] Hello World" :

    /// <summary>
    /// Method used to remove the characters betweeen certain letters in a string. 
    /// </summary>
    /// <param name="rawString"></param>
    /// <param name="enter"></param>
    /// <param name="exit"></param>
    /// <returns></returns>
    public static string RemoveFragmentsBetween(this string rawString, char enter, char exit) 
    {
        if (rawString.Contains(enter) && rawString.Contains(exit))
        {
            int substringStartIndex = rawString.IndexOf(enter) + 1;
            int substringLength = rawString.LastIndexOf(exit) - substringStartIndex;

            if (substringLength > 0 && substringStartIndex > 0)
            {
                string substring = rawString.Substring(substringStartIndex, substringLength).RemoveFragmentsBetween(enter, exit);
                if (substring.Length != substringLength) // This would mean that letters have been removed
                {
                    rawString = rawString.Remove(substringStartIndex, substringLength).Insert(substringStartIndex, substring).Trim();
                }
            }

            //Source: /questions/131476/remove-text-in-between-delimiters-in-a-string-using-a-regex/790342#790342
            Regex regex = new Regex(String.Format("\\{0}.*?\\{1}", enter, exit));
            return new Regex(" +").Replace(regex.Replace(rawString, string.Empty), " ").Trim(); // Removing duplicate and tailing/leading spaces
        }
        else
        {
            return rawString;
        }
    }

Использование этого метода в предлагаемом случае выглядит следующим образом:

string testString = "[Test 1 [[Test2] Test3]] Hello World";
testString.RemoveFragmentsBetween('[',']');

Возврат строки "Hello World".

Ответ 5

Используйте следующее Regex

(\{\S*\})

Что делает это регулярное выражение, он заменяет любые вхождения {word} с измененнымWord, который вы хотите заменить.

Пример кода С#:

 static readonly Regex re = new Regex(@"(\{\S*\})", RegexOptions.Compiled);
        /// <summary>
        /// Pass text and collection of key/value pairs. The text placeholders will be substituted with the collection values.
        /// </summary>
        /// <param name="text">Text that containes placeholders such as {fullname}</param>
        /// <param name="fields">a collection of key values pairs. Pass <code>fullname</code> and the value <code>Sarah</code>. 
        /// DO NOT PASS keys with curly brackets <code>{}</code> in the collection.</param>
        /// <returns>Substituted Text</returns>
        public static string ReplaceMatch(this string text, StringDictionary fields)
        {
            return re.Replace(text, match => fields[match.Groups[1].Value]);
        }

В предложении, например

Regex Hero является оператором {онлайн {Silverlight} Regular} в реальном времени Tester.

Он заменит только {Silverlight} и не будет начинаться с первой скобки {bracket to the last}.