Из предложенных вариантов использовал RegexReplace2 как компактную и вполне выдавала ожидаемое, но столкнулся с проблемой
#RegExp = 0
Define Path$ = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\7-Zip\7-Zip File Manager"
CreateRegularExpression(#RegExp , "(^.{3,11}/|.{11})(.*)(/.{6,27}|.{27})$" )
Debug RegexReplace2(#RegExp, Path$, "\1...\3" )выдаёт "C:\ProgramD...ms-Zip-Zip File Manager", то есть в пути \7 была удалена как 7 группа. Начал изучать функцию, в итоге некоторая оптимизация:
EnableExplicit
#RegExp = 0
Procedure.s RegexReplace2(RgEx, *Result.string, Replace1$)
Protected i, CountGr, Pos, Offset = 1
Protected Result$, Replace$
Protected NewList item.s()
Protected Count, Len, *Point
CountGr = CountRegularExpressionGroups(RgEx)
; Debug CountGr
If CountGr > 9
CountGr = 9
EndIf ; ограничение групп, только обратные ссылки \1 .. \9
Protected re, MaxGr = -1, tmp
; Здесь ищем максимальное число групп указанных в тексте замены и соответственно не обрабатываем группы больше максимальной
re = CreateRegularExpression(#PB_Any, "\\(\d)" ) ; Проверять правильность не нужно так как это внутренняя функция
If ExamineRegularExpression(re, Replace1$)
While NextRegularExpressionMatch(re)
tmp = Asc(RegularExpressionMatchString(re)) - 48
If tmp > MaxGr
MaxGr = tmp
EndIf
Wend
EndIf
; Если число групп например 7, а в замене максимальная группа 4, то обрабатываем в цикле до 4, а не до 7
If CountGr > MaxGr
CountGr = MaxGr
EndIf
If ExamineRegularExpression(RgEx, *Result\s)
While NextRegularExpressionMatch(RgEx)
Pos = RegularExpressionMatchPosition(RgEx)
Replace$ = ReplaceString(Replace1$,"\0", RegularExpressionMatchString(RgEx)) ; обратная ссылка \0
For i = 1 To CountGr
Replace$ = ReplaceString(Replace$, "\"+Str(i), RegularExpressionGroup(RgEx, i))
Next
; Result$ + часть строки между началом и первым совпадением или между двумя совпадениями + результат подстановки групп
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())
Len=0
ForEach item()
Len + Len(item()) ; вычисляем длину данных для вмещения частей текста
Next
*Result\s = Space(Len) ; создаём строку забивая её пробелами
*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
Что здесь есть?
1. Функция CountRegularExpressionGroups() была внутри цикла, но она из ID регвыра выдаёт группы, то есть не найденное, а по количеству скобок в регулярном выражении, ведь оно выдаёт это число не после того как что-то найдёт, а анализируя регвыр. То есть вытащил из цикла и поставил выше.
2. Там было удаление ссылок на несуществующие группы, то есть если в регвыр 3 группы, а в строке встречается \7, то удаляем \7 так как таких групп нет. Но автор регвыра скорее всего значет число групп в регвыре и правильно указывает ссылки и вряд ли укажет число группы, которой нет в регвыр, поэтому удаление ссылок скорее всего удалить обычный текст.
For GroupNumber=GroupCount+1 To 9 ; отсутствующие группы на пустые строки Replacing = ReplaceString(Replacing,"\"+Str(GroupNumber),"") Next
Но можно предположить что в тексте \3 может оказаться текстом, а не группой, как разруливать такой вариант? В AutoIt3 в этом случае предупреждает, если вы хотите избежать этой проблемы, то указывайте группы как \{3}, то есть вероятность такой комбинации в тексте более маловероятна, ну и к тому же это позволяет указать группы более 9, например \{45}, в противном случае это бы воспринималась как группа 4, а 5 как текст.
3. Изначально, когда я не понял суть функции RegexReplace2 я посчитал, что функция обрабатывает 9 групп несмотря на то, что у меня в регвыре 3 группы и ссылка на \3 максимальная. Решил, что надо в тексте замены найти максимальный номер группы и добавил блок с переменной MaxGr отделённый пустыми строками, его в принципе можно удалить, так как выяснилось что CountRegularExpressionGroups выдаёт то что нужно, и нет смысла искать максимальную ссылку, потому что если регвыр составлен правильно, то никто не будет плодить группы, которые не используются, так как их можно пометить как (?:...) - группа которая не возвращается в виде ссылки на группу, а используется например для выбора ИЛИ, например (?:ъ|ь). Оставил этот блок для примера, но его надо убрать.
4. Переименовал переменные, счётчик в цикле заменил на "i", использовал $ в строковых переменных, чтобы было явно видно.
5. Объединение строк сделал через работу с памятью, иначе на больших текста это будет работать медленно.
6. RegexReplace1 и RegexReplace3 у меня вообще ошибку выдают, может проблема 32 бит или ANSI?
Отредактировано AZJIO (14.10.2021 12:41:53)


пока вроде все в порядке... тыщ 150 уже строк. вроде бы нигде еще не запарился