как найти позиции индекса определенного тега BBCode (Regex)

У меня есть строка, скажем:

[s]AB[/s]23[sb]45[/sb]AB45ABABAB

Я хочу найти все индексы, окруженные тегом, содержащим букву s, включая [s] и [sb].

Вызов функции findIndices("[s]01[/s]23[sb]45[/sb]AB45ABABAB", "s") вернет список [0, 1, 4, 5 ]. Обратите внимание, что индексы игнорируют все коды BBCode. Другими словами, он считает, что индекс первого символа «А» равен 0, а не 3.

Как реализовать findIndices в C#. Я пытался использовать System.Text.RegularExpressions, но у меня возникли проблемы, трудность заключается в поиске индекса относительно строки, из которой удален BBCode.


person James Johnson    schedule 21.08.2018    source источник
comment
Вы не можете сделать это только с помощью регулярного выражения. Смотрите мой ответ.   -  person Laurianti    schedule 27.08.2018
comment
@Laurianti, в зависимости от того, как он должен обрабатывать плохо вложенные теги, регулярное выражение может быть идеальным для этого.   -  person Nissa    schedule 04.09.2018


Ответы (2)


Это всего лишь пример, вы можете попробовать этот способ, протестируйте здесь: http://rextester.com/FMTZ35054

    public class Entity
    {
        public string Text {get; set;}
        public int Index {get; set;}

        public int CountDirty {get; set;}

        public int CountClean {get; set;}
        public int CountGross {get; set;}

        public int IndexStart {get; set;}
        public int IndexEnd {get; set;}

        public int IndexStartClean {get; set;}
        public int IndexEndClean {get; set;}

        public int IndexStartGross {get; set;}
        public int IndexEndGross {get; set;}

        public int CountBefore {get;set;}
        public int CountAfter {get;set;}
    }

    public static List<Entity> findIndices(string text)
    {
        string regex = @"(\[[a-zA-Z]*\])(.*?)(\[/[[a-zA-Z]*\])";
        Regex r = new Regex(regex);

        MatchCollection matches = r.Matches(text);

        List<Entity> list = new List<Entity>();

        int accumulation = 0;
        foreach (Match match in matches)
        {
            Entity t = new Entity();

            string stringa2 = match.ToString();

            t.CountBefore = match.Groups[1].ToString().Count();
            t.CountAfter = match.Groups[3].ToString().Count();

            t.CountClean = match.Groups[2].ToString().Count();
            t.CountGross = match.ToString().Count();
            t.CountDirty = t.CountClean - t.CountGross;
            t.Text = stringa2;
            t.IndexStart = match.Index;
            t.IndexEnd = match.Index + t.CountGross - 1;

            t.IndexStartGross = t.IndexStart + t.CountBefore;
            t.IndexEndGross = t.IndexStartGross + t.CountClean - 1;

            t.IndexStartClean = t.IndexStartGross - t.CountBefore - accumulation;
            t.IndexEndClean = t.IndexStartClean + t.CountClean - 1;

            list.Add(t);

            accumulation += t.CountBefore + t.CountAfter;
        }

        return list;
    }

А это реализация:

        List<Entity> list = findIndices("[s]AB[/s]23[sb]45[/sb]AB45ABABAB[a]test[/a]");

        for (var i = 0; i < list.Count; i++)
        {
            var l = list[i];

            Console.WriteLine("Text = " + l.Text);

            Console.WriteLine("IndexStartClean = " + l.IndexStartClean);
            Console.WriteLine("IndexEndClean = " + l.IndexEndClean);

            Console.WriteLine("---");
        }
person Laurianti    schedule 22.08.2018
comment
Вы легенда. Спасибо! - person James Johnson; 12.09.2018

Такой шаблон регулярного выражения (?<=[^/]s.?\]).+?(?=\[) будет соответствовать, например. AB и 45

Мы проверяем (смотрим назад), есть ли позади нас s и ], но нет /, а затем сопоставляем символы, пока не наткнемся на [. Могут быть крайние случаи, которые я пропустил, поэтому будьте осторожны и проверьте это.

(Если вам нужны именно индексы, вы можете получить их из объектов соответствия регулярных выражений)

person N.D.C.    schedule 21.08.2018