Code: Select all
EnableExplicit
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
Procedure Brackets(*Str.String, Array ArrBrackets(1), Array ArrBrackets2(1))
Protected Toggle = 2, tmp$, Count, Pos, i
#RegExp = 0
If CreateRegularExpression(#RegExp, "\(([^()]+?)\)", #PB_RegularExpression_NoCase)
Repeat
; For i = 1 To 9
tmp$ = *Str\s
RegexReplace2(#RegExp, *Str, Chr(Toggle) + "\1" + Chr(Toggle))
If tmp$ = *Str\s
Break
EndIf
tmp$ = *Str\s
Toggle = Bool(Not (Toggle - 1)) + 1
; Next
ForEver
Else
Debug RegularExpressionError()
EndIf
Count = CountString(*Str\s, Chr(2))
ReDim ArrBrackets(Count)
For i = 1 To Count
Pos = FindString(*Str\s, Chr(2), Pos + 1)
If Pos
ArrBrackets(i) = Pos - 1
EndIf
Next
Pos = 0
Count = CountString(*Str\s, Chr(1))
ReDim ArrBrackets2(Count)
For i = 1 To Count
Pos = FindString(*Str\s, Chr(1), Pos + 1)
If Pos
ArrBrackets2(i) = Pos - 1
EndIf
Next
; ReplaceString(*Str\s, Chr(2), "(", #PB_String_InPlace)
; ReplaceString(*Str\s, Chr(1), ")", #PB_String_InPlace)
; Debug *Str\s
EndProcedure
Define Txt.String
Define MyStr$, i
Define Dim ArrBr(0)
Define Dim ArrBr2(0)
Txt\s = "word (word) (word\(f\)word) (word(f)word)"
MyStr$ = Txt\s
Brackets(Txt, ArrBr(), ArrBr2())
; MyStr$ = "word (word) (word\(f\)word) (word(f)word)"
; Brackets(@MyStr$, ArrBr())
Debug "Count = " + Str(ArraySize(ArrBr()))
For i = 1 To ArraySize(ArrBr(), 2)
Debug Str(ArrBr(i))
Next
Debug "Count = " + Str(ArraySize(ArrBr2()))
For i = 1 To ArraySize(ArrBr2(), 2)
Debug Str(ArrBr2(i))
Next
Enumeration
#Brackets1
#Brackets2
EndEnumeration
Define *Text
Define Toggle
If Not InitScintilla()
End
EndIf
If OpenWindow(0, 0, 0, 630, 190, "ScintillaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScintillaGadget(0, 10, 10, 620, 170, 0)
*Text = UTF8(MyStr$)
ScintillaSendMessage(0, #SCI_SETTEXT, 0, *Text)
FreeMemory(*Text)
ScintillaSendMessage(0, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 16)
ScintillaSendMessage(0, #SCI_INDICSETSTYLE, #Brackets1, #INDIC_STRAIGHTBOX)
ScintillaSendMessage(0, #SCI_INDICSETFORE, #Brackets1, $9900FF)
ScintillaSendMessage(0, #SCI_INDICSETUNDER, #Brackets1, 1)
ScintillaSendMessage(0, #SCI_INDICSETALPHA, #Brackets1, 127)
ScintillaSendMessage(0, #SCI_INDICSETSTYLE, #Brackets2, #INDIC_STRAIGHTBOX)
ScintillaSendMessage(0, #SCI_INDICSETFORE, #Brackets2, $0099FF)
ScintillaSendMessage(0, #SCI_INDICSETUNDER, #Brackets2, 1)
ScintillaSendMessage(0, #SCI_INDICSETALPHA, #Brackets2, 127)
For i = 1 To ArraySize(ArrBr())
ScintillaSendMessage(0, #SCI_SETINDICATORCURRENT, Toggle, #INDIC_STRAIGHTBOX)
ScintillaSendMessage(0, #SCI_INDICATORFILLRANGE, ArrBr(i), 1)
Next
Toggle = Bool(Not Toggle)
For i = 1 To ArraySize(ArrBr2())
ScintillaSendMessage(0, #SCI_SETINDICATORCURRENT, Toggle, #INDIC_STRAIGHTBOX)
ScintillaSendMessage(0, #SCI_INDICATORFILLRANGE, ArrBr2(i), 1)
Next
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf