PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » PureBasic для Windows » Ссылки на группы в регулярном выражении


Ссылки на группы в регулярном выражении

Сообщений 1 страница 16 из 16

1

Из предложенных вариантов использовал 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)

0

2

AZJIO написал(а):

7. RegexReplace1 и RegexReplace3 у меня вообще ошибку выдают

Я об этом писал, что в новых версиях перестало работать.

использовал $ в строковых переменных, чтобы было явно видно

И зачем эта архаика и возврат к мрачному прошлому, когда в Бейсике не было описания типов переменных?

AZJIO написал(а):

Но можно предположить что в тексте \3 может оказаться текстом, а не группой, как разруливать такой вариант? В AutoIt3 в этом случае предупреждает, если вы хотите избежать этой проблемы, то указывайте группы как \{3}, то есть вероятность такой комбинации в тексте более маловероятна

В любом случае остаётся вероятность наступить на грабли. Надо делать экранирующие символы. Мне, когда писал эти функции, нужны были замены в именах файлов, а там символ \ не встречается. Поэтому я упростил.

0

3

Smitis написал(а):

И зачем эта архаика и возврат к мрачному прошлому, когда в Бейсике не было описания типов переменных?

т.е. перейти на венгерскую нотацию?

0

4

AZJIO написал(а):

т.е. перейти на венгерскую нотацию?

Зачем?

П.С.
Хотя со временем я венгерскую нотацию стал использовать всё больше. Правда, в своём первоначальном варианте, который теперь называется "для приложений"
http://accwin.narod.ru/txt/01_h_notation.htm

0

5

Продолжение из другой темы.

AZJIO написал(а):

Всмысле, что \1 может оказаться текстом а не группой?

Может. И знать заранее мы это не можем, разве только для некоторых специфичных случаев (например, как имена файлов, о чём я уже писал выше).

Пример.
регэксп: "(\D+\d+)(\D+)" с заменой на "\2\1" - переставить местами две части выражения (всё, что после первых цифр - в начало).
для строки "@#$%^8qwerty" работает.
для строки "\2aa" неправильный результат.
То есть, функции с использованием ReplaceString не будут универсальными. Ограничение - в строке поиска и в строке замены не должно быть символов "\", иначе правильный результат не гарантируется.
Единственный выход, это посимвольный разбор.

0

6

Не тестил группы \0 и разные комбинации, но вот новый код.

Код:
Structure ReplaceGr
  pos.i
  ngr.i
  group.s
EndStructure


; https://www.purebasic.fr/english/viewtopic.php?p=575871
Procedure.s RegexReplace2(RgEx, *Result.string, Replace0$)
	Protected i, CountGr, Pos, Offset = 1
	Protected Result$, Replace$
	Protected NewList item.s()
	Protected LenT, *Point ;, Count
	Protected RE2
	Protected NewList ReplaceGr.ReplaceGr()

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

	If ExamineRegularExpression(RgEx, *Result\s)
    
    ; Уникальные неэкранированные группы
    RE2 = CreateRegularExpression(#PB_Any, "(?<!\\)(?:\\\\)*(?:\\)\K(\d)")
    If RE2
    	If ExamineRegularExpression(RE2, Replace0$)
        While NextRegularExpressionMatch(RE2)
        	If AddElement(ReplaceGr())
            ReplaceGr()\pos = RegularExpressionGroupPosition(RE2, 1) ; позиция
            ReplaceGr()\ngr = ValD(RegularExpressionGroup(RE2, 1)) ; номер группы
            ReplaceGr()\group = RegularExpressionGroup(RE2, 1) ; текст группы
        	EndIf
        Wend
    	EndIf
    EndIf
    SortStructuredList(ReplaceGr(), #PB_Sort_Descending, OffsetOf(ReplaceGr\pos), TypeOf(ReplaceGr\pos))

    
    While NextRegularExpressionMatch(RgEx)
    	Pos = RegularExpressionMatchPosition(RgEx)
    	ForEach ReplaceGr()
        If ReplaceGr()\ngr = 0
        	Replace0$ = ReplaceString(Replace0$,"\0", RegularExpressionMatchString(RgEx), #PB_String_NoCase, ReplaceGr()\pos - 1, 1) ; обратная ссылка \0
        	DeleteElement(ReplaceGr()) 
        EndIf
    	Next
    	Replace$ = Replace0$

    	ForEach ReplaceGr()
        Replace$ = ReplaceString(Replace$, "\" + ReplaceGr()\group, RegularExpressionGroup(RgEx, ReplaceGr()\ngr), #PB_String_NoCase, ReplaceGr()\pos - 1, 1)
    	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

Что тут нового:
Два раза переписывал, и пришёл к выводу что со структурой экономичней и точней.
1. Рег.выр. анализируется и все ссылки на группы получают свою информацию в списке. То есть сохраняется группа и позиция где найдено, что позволит потом перейти к этой позиции и заменять 1 раз.
2. Изначально делал массив, удаление дубликатов, сортировку, чтобы \0 был первым в списке, но проблема такого решения оставалась, если я начну заменять точно найденные ссылки, то я могу испортить и не найденные, то есть для каждой группы \1, \2 придётся генерировать свой рег.выр. для его точного поиска. Чтобы такое не делать выгодно сохранить позиции и тогда отпадает необходимость удалять дубликаты и делать регвыр на каждую группу, а использовать ReplaceString() с заменой в позиции 1 раз.
3. Чтобы позиции не нарушались делается сортировка в обратном порядке по позиции и заменяются от конца в начало.

4. Кажется не сложно в этом контексте добавить поиск групп \{1} и условие, если найдено, то не искать группы типа \1, что позволит автоматически переключить рег.выр. на безопасный поиск групп.

Отредактировано AZJIO (20.05.2022 16:35:06)

0

7

AZJIO
Списки, сортировка, вторая регулярка... Как-то всё избыточно и не оптимально, imho.
Хотя мысль предварительно обработать Replace мне понравилась.

0

8

Надо будет Static использовать, чтобы компилиповать рег.выр один раз. Эта избыточность быстро создается, там же строка замены обычно 10-100 символов, а список из 2-3 элементов. Позже таймером проверю скорость. И надо учитывать, что при обработке текстов всё равно основная нагрузка это обрабатываемый текст, так что привнесение 1% затрат не критично к производительности.

0

9

Протестировано с \0, это тоже требует позиции, то есть предыдущий вариант имеет гарантированную ошибку.
Добавлено - если группы не найдено то используется нативная функция ReplaceRegularExpression() и выпрыгивание из функции (для быстроты).
Упрощён регвыр "\\\d" для поиска групп, так как предыдущий вариант мог бы использоваться в строке поиска, а не в строке замены, где экранирование не требуется так как это не шаблон регулярного выражения, а просто текст замены, в котором допускаются ссылки группы.
Структура формируется для максимальной готовности, чтобы не делать конкатенацию строк в цикле поиска.

Код:
EnableExplicit

Structure ReplaceGr
  pos.i
  ngr.i
  group.s
EndStructure


; https://www.purebasic.fr/english/viewtopic.php?p=575871
Procedure RegexReplace2(RgEx, *Result.string, Replace0$)
	Protected i, CountGr, Pos, Offset = 1
	Protected Replace$
	Protected NewList item.s()
	Protected LenT, *Point
; 	Static RE2
	Protected RE2
	Protected NewList ReplaceGr.ReplaceGr()

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

	If ExamineRegularExpression(RgEx, *Result\s)
    
    ; Поиск ссылок на группы в поле замены в регвыр
;     If Not RE2 ; вариант для Static, но неуниверсальность в отдельной функции удаления регвыра
;     	RE2 = CreateRegularExpression(#PB_Any, "\\\d")
;     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, Replace$)
    	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_NoCase, ReplaceGr()\pos, 1)
        Else
        	Replace$ = ReplaceString(Replace$, ReplaceGr()\group, RegularExpressionMatchString(RgEx), #PB_String_NoCase, 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

Text\s = "\2aa"
CreateRegularExpression(#RegExp , "(\D+\d+)(\D+)" )
RegexReplace2(#RegExp, @Text, "\2\1" )
FreeRegularExpression(#RegExp)
Debug Text\s

Text\s = "\2aa"
CreateRegularExpression(#RegExp , "(\D+\d+)(\D+)" )
RegexReplace2(#RegExp, @Text, "\0\2" )
FreeRegularExpression(#RegExp)
Debug Text\s

0

10

Я потом такой свой вариант опробую - при предварительной обработке Replace заменить обратные ссылки на, например, Chr($F0000), Chr($F0001), Chr($F0002)... - символы юникода для частного использования. Тогда StringReplace заменит эти символы без проблем, конфликта не возникнет.

0

11

А вообще, надо на ассме пройтись по Replace от первого символа до предпоследнего. Если встречаем \ и за ним \, заменяем на какую-нибудь суррогатную пару (32 бита), которую обработаем уже в самом конце одной StringReplace заменив на \. Остальные пары \+цифра (16+16 бит) заменяем на соответствующую суррогатную пару (те же 32 бита). Как-то так.

0

12

Smitis
Вообще то у меня нет предварительной обработки. Я не изменяю переменную Replace, регвыр просто ищет в ней позиции замены. Если мы говорим о производительности, то замены в Replace на 00 и 01 и т.д. в итоге не будут производительны. Если я получил позиции, что предоставляет регвыр, то при замене, как раз таки более производительно встать сразу на указанную позицию по указателю и сделать однократную замену, то есть нет поиска по строке. Второе, зачем обязательно избавляться от регвыр? У нас по функционалу движок уже встроен, и потеря скорости могла бы быть на компиляции регвыр, но мы вполне можем скомпилировать при первом вызове, я уже спросил на офиц.форуме, что #PB_Any при закрытии программы освобождается автоматически, значит мы в функции можем не контролировать закрытие. И даже если не делать так, то компиляция такого простого регвыра без возвратов и ветвистости происходит очень быстро, фактически это статический текст, наклонная черта и за ней символ с кодом от 48 до 57. Третье, замена на 00 и 01 и т.д. ограничивает использование, так как строка всё кроме 00, значит 01 может оказаться в строке.

0

13

AZJIO
Под предварительной обработкой я имел ввиду создание списка с позициями. Само по себе создания динамического списка, имхо, дело не быстрое. А замена символов по месту будет практически мгновенное. Конечно, выиграем на замене, потеряем немного на StringReplace (немного, потому что в любом случае мы от неё не избавляемся).
И я предлагал заменять не на символы 00, 01, а на суррогатные пары из https://ru.wikipedia.org/wiki/Области_д … льзования. Два обычных символа юникода как раз отлично заменяться на один.

0

14

Smitis написал(а):

создания динамического списка, имхо, дело не быстрое

это почему?
Шаг 1. Создаём указатель.
Шаг 2. Добавлением элемента, тоже как добавление переменной, создаём переменную и записываем указатель на неё следующим указателем.
То есть от первого указателя идут указатели на строки, или в начале строки 2 указателя, первый начало, второй на следующий элемент. Но факт что на 2-3 группы (2-3 элемента списка) тратится меньше времени чем присвоение данных локальным переменным.
Самая медленная функция это замена, где мы находим регвыр по шаблону, разбираем его на группы, делаем замену, и потом формируем последовательность кусков. Эта часть кода работает взависимости от размера текста, если мы обрабатываем 100 кб данных, там 1000 найденных для замены. А  3 элемента списка формируются 1 раз. Это медленно если обрабатывать строку из 3 символов, тогда да, обслуживающая часть кода будет работать дольше чем обработка собственно самого 3-х буквенного текста.

Кстати, если задать длину поля строки group.s{2}, то ещё быстрей, там же группы "\1" - 2 символа.

Мы не знаем какой текст будет обрабатываться, если UTF16, то там ширина символов одинаковая и суррогатный символ вполне может быть частью текста, может кто-то тоже умный и использует этот символ для разметки некоторой базы данных в виде текста. Мы ранее на форуме AutoIt3 писали разделитель (функцию Split) с помощью регвыр, так вот там найденное меняли на вот эти на эти 01 или 02 за первый проход, а потом делили уже используя 02 как разделитель, но перед этим сначала в цикле проверяли какой из символов от 01 до 31 отсутствует в тексте и уже потом делали финт. Так что если есть возможность избежать, то лучше избежать или для идеальности проверять что символов нет в тексте, а это уже потеря производительности.

Отредактировано AZJIO (21.05.2022 20:10:46)

0

15

AZJIO написал(а):

Мы не знаем какой текст будет обрабатываться, если UTF16

Знаем.

AZJIO написал(а):

суррогатный символ вполне может быть частью текста

Эти - не могут.

AZJIO написал(а):

меняли на вот эти на эти 01 или 02 за первый проход, а потом делили уже используя 02 как разделитель

Опять двадцать пять. :(

0

16

Smitis
Хозяин барин )))

Я тут идейку вставил, в функцию добавил флаг-параметр Escaped, чтобы в поле замены поддержать переносы строк и табуляцию, которые иногда интерфейс не позволяет вставить, например в ComboBoxGadget или StringGadget

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

0


Вы здесь » PureBasic - форум » PureBasic для Windows » Ссылки на группы в регулярном выражении