Описание функции


RegexReplace2

Замена с помощью регулярного выражения с использованием ссылок на группы в строке замены.

RegexReplace2(RgEx, *Result.string, Replace0$ [, Escaped = 0 ])

Параметры

RgEx Идентификатор регулярного выражения созданный с помощью CreateRegularExpression()
*Result.string Структура на строку, которая будет обработана
Replace0$ То чем заменить, с поддержкой ссылок на группы \1 - \9
Escaped Обработка метасимволов \r, \n, \t, \f в строке замены Replace0$
0 - не обрабатывать
1 - обрабатывать

Возвращаемое значение

Возвращает изменённую строку или исходную если ничего не найдено.

Примечания

Если строка замены не использует ссылки на группы, то лучше использовать нативную функцию ReplaceRegularExpression(), так как это будет работать быстрее.
Если невозможно явно указать символы CR, LF, TAB, FF в строке замены, например если строка замены считывается из комбобокса, то включите флаг обработки метасимволов Escaped и используйте \r, \n, \t, \f.

Пример

; AZJIO
; https://www.purebasic.fr/english/viewtopic.php?p=575871
Structure ReplaceGr
    pos.i
    ngr.i
    group.s
EndStructure

Procedure RegexReplace2(RgEx, *Result.string, Replace0$, Escaped = 0)
    Protected i, CountGr, Pos, Offset = 1
    Protected Replace$
    Protected NewList item.s()
    Protected LenT, *Point
;     Static RE2
;     Static RE3
    Protected RE2
    Protected NewList ReplaceGr.ReplaceGr()

    CountGr = CountRegularExpressionGroups(RgEx)
    ; ограничение групп, только обратные ссылки \1 .. \9
    If CountGr > 9
        CountGr = 9
    EndIf

    If ExamineRegularExpression(RgEx, *Result\s)

        ; Поиск Esc-символов в поле замены регвыр
        If Escaped
            Replace0$ = ReplaceString(Replace0$, "\r", #CR$)
            Replace0$ = ReplaceString(Replace0$, "\n", #LF$)
            Replace0$ = ReplaceString(Replace0$, "\t", #TAB$)
            Replace0$ = ReplaceString(Replace0$, "\f", #FF$)
        EndIf

        ; Поиск ссылок на группы в поле замены регвыр
        RE2 = CreateRegularExpression(#PB_Any, "\\\d")
        If RE2
            If ExamineRegularExpression(RE2, Replace0$)
                While NextRegularExpressionMatch(RE2)
                    If AddElement(ReplaceGr())
                        ReplaceGr()\pos = RegularExpressionMatchPosition(RE2) ; позиция
                        ReplaceGr()\ngr = ValD(Right(RegularExpressionMatchString(RE2), 1)) ; номер группы
                        ReplaceGr()\group = RegularExpressionMatchString(RE2) ; текст группы
                    EndIf
                Wend
            EndIf
            FreeRegularExpression(RE2) ; убрать строку при Static
        EndIf
        If Not ListSize(ReplaceGr())
            *Result\s = ReplaceRegularExpression(RgEx, *Result\s, Replace0$)
            ProcedureReturn
        EndIf
;         Сортировка по позиции, чтобы делать замены с конца и не нарушались ранее найденные позиции
        SortStructuredList(ReplaceGr(), #PB_Sort_Descending, OffsetOf(ReplaceGr\pos), TypeOf(ReplaceGr\pos))

        While NextRegularExpressionMatch(RgEx)
            Pos = RegularExpressionMatchPosition(RgEx)
            Replace$ = Replace0$

            ForEach ReplaceGr()
                If ReplaceGr()\ngr
                    Replace$ = ReplaceString(Replace$, ReplaceGr()\group, RegularExpressionGroup(RgEx, ReplaceGr()\ngr), #PB_String_CaseSensitive, ReplaceGr()\pos, 1)
                Else
                    Replace$ = ReplaceString(Replace$, ReplaceGr()\group, RegularExpressionMatchString(RgEx), #PB_String_CaseSensitive, ReplaceGr()\pos, 1) ; обратная ссылка \0
                EndIf
            Next
            ; item() = часть строки между началом и первым совпадением или между двумя совпадениями + результат подстановки групп

            If AddElement(item())
                item() = Mid(*Result\s, Offset, Pos - Offset) + Replace$
            EndIf
            Offset = Pos + RegularExpressionMatchLength(RgEx)
        Wend
        If AddElement(item())
            item() = Mid(*Result\s, Offset)
        EndIf

        ; Формирования текстового списка
        ; Debug "Count = " + Str(ListSize(item()))
;         Count = ListSize(item())
        LenT = 0
        ForEach item()
            LenT + Len(item()) ; вычисляем длину данных для вмещения частей текста
        Next

        *Result\s = Space(LenT) ; создаём строку забивая её пробелами
        *Point = @*Result\s ; Получаем адрес строки
        ForEach item()
            CopyMemoryString(item(), @*Point) ; копируем очередной путь в указатель
        Next
        ; Конец => Формирования текстового списка

        FreeList(item()) ; удаляем список, хотя в функции наверно это не требуется
    EndIf
EndProcedure


#RegExp = 0
Define Text.string
Text\s = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\7-Zip\7-Zip File Manager"
CreateRegularExpression(#RegExp , "(^.{3,11}/|.{11})(.*)(/.{6,27}|.{27})$" )
RegexReplace2(#RegExp, @Text, "\1...\3" )
FreeRegularExpression(#RegExp)
Debug Text\s

Text\s = "56868797689645"
CreateRegularExpression(#RegExp , "(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))" )
RegexReplace2(#RegExp, @Text, "\1 " )
FreeRegularExpression(#RegExp)
Debug Text\s