Описание функции
RegexReplace2
Замена с помощью регулярного выражения с использованием ссылок на группы в строке замены.
RegexReplace2(RgEx, *Result.string, Replace0$ [, Escaped = 0 ])
Параметры
RgEx | Идентификатор регулярного выражения созданный с помощью CreateRegularExpression() |
*Result.string |
Структура на строку, которая будет обработана |
Replace0$ |
То чем заменить, с поддержкой ссылок на группы \1 - \9 |
Escaped |
Обработка метасимволов \r, \n, \t, \f в строке замены Replace0$ 0 - не обрабатывать 1 - обрабатывать |
Возвращаемое значение
Возвращает изменённую строку или исходную если ничего не найдено. |
Примечания
Если строка замены не использует ссылки на группы, то лучше использовать нативную функцию ReplaceRegularExpression(), так как это будет работать быстрее.Пример
; 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