Найти все подстроки между двумя строками - PullRequest
12 голосов
/ 31 марта 2010

Мне нужно получить все подстроки из строки.
Например:

StringParser.GetSubstrings("[start]aaaaaa[end] wwwww [start]cccccc[end]", "[start]", "[end]");

, который возвращает 2 строки "aaaaaa" и "cccccc" Предположим, у нас есть только один уровень вложенности. Не уверен насчет регулярного выражения, но я думаю, что оно будет полезным.

Ответы [ 6 ]

33 голосов
/ 31 марта 2010
private IEnumerable<string> GetSubStrings(string input, string start, string end)
{
    Regex r = new Regex(Regex.Escape(start) + "(.*?)" + Regex.Escape(end));
    MatchCollection matches = r.Matches(input);
    foreach (Match match in matches)
        yield return match.Groups[1].Value;
}
5 голосов
/ 31 марта 2010

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

public static IEnumerable<string> EnclosedStrings(
    this string s, 
    string begin, 
    string end)
{
    int beginPos = s.IndexOf(begin, 0);
    while (beginPos >= 0)
    {
        int start = beginPos + begin.Length;
        int stop = s.IndexOf(end, start);
        if (stop < 0)
            yield break;
        yield return s.Substring(start, stop - start);
        beginPos = s.IndexOf(begin, stop+end.Length);
    }           
}
2 голосов
/ 31 марта 2010

Вы можете использовать регулярное выражение, но не забудьте вызвать Regex.Escape для ваших аргументов:

public static IEnumerable<string> GetSubStrings(
   string text,
   string start,
   string end)
{
    string regex = string.Format("{0}(.*?){1}",
        Regex.Escape(start), 
        Regex.Escape(end));

    return Regex.Matches(text, regex, RegexOptions.Singleline)
        .Cast<Match>()
        .Select(match => match.Groups[1].Value);
}

Я также добавил параметр SingleLine , чтобы он совпадал, даже если в вашем тексте есть новые строки.

2 голосов
/ 31 марта 2010

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

Вы должны иметь возможность использовать регулярные выражения. Вложенность может сделать его немного более сложным, но все же выполнимым (в зависимости от того, что вы ожидаете, чтобы соответствовать во вложенных сценариях). Нечто подобное должно начать вас:

var start = "[start]";
var end = "[end]";
var regEx = new Regex(String.Format("{0}(.*){1}", Regex.Escape(start), Regex.Escape(end)));
var source = "[start]aaaaaa[end] wwwww [start]cccccc[end]";
var matches = regEx.Match( source );

Это должно быть тривиально, чтобы обернуть код выше в функцию, соответствующую вашим потребностям.

0 голосов
/ 09 июля 2017

Метод без регулярных выражений:

public static List<string> extract_strings(string src, string start, string end)
{
    if (src.IndexOf(start) > 0)
    {
        src = src.Substring(src.IndexOf(start));
    }
    string[] array1 = src.Split(new[] { start }, StringSplitOptions.None);
    List<string> list = new List<string>();
    foreach (string value in array1)
    {
        if (value.Contains(end))
        {
            list.Add(value.Split(new[] { end }, StringSplitOptions.None)[0]);
        }
    }
    return list;
}
0 голосов
/ 13 февраля 2013

Мне было скучно, и поэтому я сделал бесполезный микро-тест, который «доказывает» (на моем наборе данных, который содержит строки до 7k символов и <b> теги для параметров начала / конца), мое подозрение, что juharrРешение является самым быстрым из трех.

Результаты (1000000 итераций * 20 тестовых случаев):

juharr: 6371ms
Jake: 6825ms
Mark Byers: 82063ms

ПРИМЕЧАНИЕ. Скомпилированное регулярное выражение didnне сильно ускоряет мой набор данных.

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