Что нового

[RegExp] Обрамление подстроки тегами учитывая все вхождения

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Пытаюсь обрамить определённую подстроку тегами, но сложность в том, что нужно это сделать для всех подходящих вхождений данной подстроки.
Подстрока это посылаемые клавиши в Send(), поэтому искать её нужно исключительно в рамках кавычек, при чём как одиночных, так и двойных.

Делаю так:

Код:
$vTest = "Function ('string +{f1} and ^{f1} string')"
;$vTest = 'Function ("string +{f1} and ^{f1} string")'

$sRet = StringRegExpReplace($vTest, "(('|"")[^\2]+?)((?i)[\^+!#]*?\Q{f1}\E)([^\2]+?\2)", '\1<tag>\3</tag>\4')

ConsoleWrite($sRet & @LF)

Но как видно, заменяется только первое вхождение.

Внимание вопрос: как произвести тоже самое, но для всех вхождений? :whistle:

P.S
«\Q...\E» это для того чтобы отменить любой потенциально присутствующий служебный символ в искомой подстроке, т.к она берётся из списка поддерживаемых ключей для Send.


Добавлено:
Сообщение автоматически объединено:

Мда... оказывается есть ещё пару “правил”:

* Эти ключи не должны заменяться если они располагаются во вложенных полукруглых скобках:
Код:
$sVar = '{ {f1} }'

тут заменять не нужно.

* После найденного ключа может быть пробел а за ним цифра, и только цифра:
Код:
$sVar = '{f1 2}'

тут заменять нужно.
однако если цифра следует сразу за символом ("не пробел"), то заменять не нужно.


Добавлено:
Сообщение автоматически объединено:

Ок, последние два правила решил так:

"(('|"")[^\2\{]+?)((?i)[\^+!#]*?{f1[\h\d]*?})([^\2\}]+?\2)"



Добавлено:
Сообщение автоматически объединено:

Для правила с пробелом после ключа вроде решается так:

Код:
$sRet = StringRegExpReplace($vTest, "(('|"")[^\2]*?)((?i)[\^+!#]*?{f1(?:[\h]+?[\h\d]*?)?})([^\2]*?\2)", '\1<tag>\3</tag>\4')



* И ещё одно правило - если подстрока уже обрамлена тегами (<tag></tag>), то заменять не нужно.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Код:
$vTest = "Function('string {f1} and {f1} string') {f1}"

$sRet = StringRegExpReplace($vTest, '([\^+!#]*?{f1(?:[\h]+?[\h\d]*?)?})', '<tag>\1</tag>')

ConsoleWrite($sRet & @LF)


Вот так заменяет все вхождения, но дело в том, что то что выходит за пределы кавычек заменять не нужно, только то что попадает в границы кавычек.
 

amel27

Продвинутый
Сообщения
146
Репутация
55
CreatoR сказал(а):
дело в том, что то что выходит за пределы кавычек заменять не нужно, только то что попадает в границы кавычек.

Именно поэтому задача нерешаема за один проход: либо мы считаем заменяемой "подстрокой" всё выражение в кавычках (но не знаем кол-во макросов SEND внутри), либо макрос (но тогда теряем его положение по отношению к кавычкам). ИМХО проще сначала тегировать сами литерные строки (то, что в кавычках), а потом уже заниматься содержимым и по расставленным тегам определять местоположение макросов.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
amel27 [?]
ИМХО проще сначала тегировать сами литерные строки (то, что в кавычках), а потом уже заниматься содержимым и по расставленным тегам определять местоположение макросов.
Я пока сделал немного подругому - у меня на первом этапе все строки в кавычках помещаются в массив (на их место ставятся строки-заменитили, типа уникальных маркеров), и уже потом, на этапе восстановления этих строк, я делаю замену по нужному выражению, примерно вот так:

Код:
For $i = 0 To UBound($aStrings)-1 Step 2
		$sStrings &= $aStrings[$i] & @CRLF
	Next
	
	For $i = 1 To $aSendKeys[0]
		$sPattern = '(?i)([\^+!#]*?{' & $aSendKeys[$i] & '(?:[\h]+?[\h\d]*?)?})'
		$sStrings = StringRegExpReplace($sStrings, $sPattern, '<span class="S10">\1</span>')
	Next



Добавлено:
Сообщение автоматически объединено:

А вот как быть с вложенными полукруглыми скобками?

Код:
$sStrings = '"{Press {F1} for} help."'

$sPattern = '(?i)([\^+!#]*?{f1(?:[\h]+?[\h\d]*?)?})'
$sStrings = StringRegExpReplace($sStrings, $sPattern, '<span class="S10">\1</span>')

ConsoleWrite($sStrings & @LF)


тут замены быть не должно...
 

amel27

Продвинутый
Сообщения
146
Репутация
55
CreatoR [?]
Эти ключи не должны заменяться если они располагаются во вложенных полукруглых скобках:

Код:
$sVar = '{ {f1} }'
тут заменять не нужно.

а что это вообще значит?.. :blink:
у меня SEND на это какой-то бред выдает

А вот как быть с вложенными полукруглыми скобками?
как вариант... кстати, это вроде фигурные скобки ;)

Код:
$sPattern = '(?i)({f1(?:[\h]+[\d]+)*+(?=})(?!}(?:[^{]*{[^}]*})*[^{]*}).)'


у меня на первом этапе все строки в кавычках помещаются в массив (на их место ставятся строки-заменитили, типа уникальных маркеров), и уже потом, на этапе восстановления этих строк, я делаю замену по нужному выражению

у меня на этот счет была другая идея - построить рекурсивную ф-цию, которая бы на каждой итерации обрамляла свой стиль (скажем, четные элементы массива StringRegExp), а остальное (нечетные элементы) запускала на следующую итерацию... но при этом регулярные выражения должны строиться так, чтобы не терять текст, а только разбивать на "свой" и "чужой"... плюс в том, что алгоритм прост и легко управляем, но требует разработки специфических паттернов и без решения проблемы предкомпиляции будет очень медленным, т.к. текст будет разбиваться на все меньшие кусочки и к каждому будут применяться регулярные выражения из заданного массива
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
amel27 [?]
у меня SEND на это какой-то бред выдает
Да, но в SciTE оно не подсвечивается, а мне хотелось бы добиться полной аналогий подсветки в SciTE :smile:

как вариант... кстати, это вроде фигурные скобки
Спасибо, буду знать. А на счёт выражения, не совсем так. Если открывающей скобки нет, но есть закрывающая, то замену нужно делать. И ещё, пробел вместе с цифрой я не зря оставил, вот список нескольких таких “бредовых” строчек, где нужно и не нужно делать замену (см. комменты):

AutoIt Код (с парсированием BB-кодов):
$sStrings = '"{Press {F1} fo } help."' & @CRLF ;НЕ нужно заменять
$sStrings &= '"Press {F1} fo } help."' & @CRLF ;Нужно
$sStrings &= '"Press {F1 1} fo help."' & @CRLF ;Нужно
$sStrings &= '"Press {F1 1 } fo help."' & @CRLF ;Нужно
$sStrings &= '"Press {F1 1 1} fo help."' & @CRLF ;Нужно
$sStrings &= '"Press {F1 1 f} fo help."' & @CRLF ;НЕ нужно
$sStrings &= '"{Press {F1} fo {f1} help."' & @CRLF ;Первое вхождение НЕ нужно, второе Нужно
$sStrings &= '"{Press {F1} {fo {f1} help."' & @CRLF ;Оба вхождения НЕ нужно
$sStrings &= '"}Press {F1} }fo {f1} help."' & @CRLF ;Оба вхождения Нужно


“Нужность” и “не нужность” можно увидеть в SciTE, то что нужно будет подсвечиваться ораньжевым цветом :smile:

P.S
Кстати твой паттерн (помню я как то спрашивал, как оно правильно по русский будет, вроде “Выражение”? :smile: ) работает только для одной-последней строки, мне не хотелось бы ещё и эти строки разделять на массив и перебирать по одной.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
OffTopic:
Kaster [?]
pattern - в контексте рег. выражений будет "шаблон"
У меня «шаблон» как бы ассоциируется с чем то статичным, а «pattern» таким далеко не является, поэтому мне лично больше нравится «выражение» :whistle:
 

amel27

Продвинутый
Сообщения
146
Репутация
55
CreatoR сказал(а):
мне хотелось бы добиться полной аналогий подсветки в SciTE

гм... а оно точно надо?... в раскраске SciTE слишком много "глюков", связанных с ограниченной функциональностью лексера (результат компромисса между скоростью и возможностями)... по мне, так следует исходить прежде всего из удобства чтения и пользы раскраски, а не тратить ресурсы на воспроизведение чьих-то недоработок
:whistle:
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
amel27 [?]
а оно точно надо?... в раскраске SciTE слишком много "глюков"
Ну тут это не глюк, т.к то что не подсвечивается, работать и не будет в Send(). Поэтому в данном случае требуется соответствие. Я согласен, есть глюки у SciTE, и в своём механизме раскраски я обошел некоторые из них, например подсветка вот такого hex-числа:
AutoIt Код (с парсированием BB-кодов):
0x_000000

оно же работать не будет, зачем тогда подсвечивается префикс hex'а?


Добавлено:
Сообщение автоматически объединено:

Хм.. странно, вот так как раз работает, и не подсвечивает:
Код:
Send("{F1  f}")
 

amel27

Продвинутый
Сообщения
146
Репутация
55
CreatoR [?]
странно, вот так как раз работает, и не подсвечивает

и что подсвечивать?.. только то, что обрабатывает SEND, или всё, что между скобками?.. или нерабочие символы подсвечивать по-другому? (типа "ошибка"), или все-таки как в SciTE ? ;)
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
amel27 [?]
и что подсвечивать?.. только то, что обрабатывает SEND, или всё, что между скобками?.. или нерабочие символы подсвечивать по-другому? (типа "ошибка"), или все-таки как в SciTE ?
Так это я про SciTE, он и не подсвечивает, хотя должен подсвечивать всё на что регаирует Send (в фигурных скобках).
 
Верх