Регулярные выражения

Russian main discussion
  • Author
  • Message
Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

Serge Yolkin wrote:С какого перепугу? В первом правиле захватываем команду до первой запятой, не захватывая саму запятую, во втором - ловим то, что между неэкранированными запятыми или запятой и концом строки (не захватывая запятые - пусть раскрашиваются как разделители). Где тут каскадное наложение?
У меня задача не "отделить команды от их аргументов", т.к. это не нужно и решается весьма тривиально.
Задача - для каждой команды разделить аргументы по типам.
Serge Yolkin wrote:А Вы что же, в каждом правиле строку целиком обрабатываете? (готов офигеть от положительного ответа)
Вот ыменно! И правил получилось ~250шт.

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

YuS wrote:Имхо, для частного случая, хорошим выходом из положения, была бы возможность использования других символов для разделения частей аргументов... или это в принципе невозможно в синтаксисе того языка?
Это временный и не оптимальный выход: сейчас, в принципе существуют #CommentFlag, #Delimiter, #DerefChar и #EscapeChar, но в разрабатываемой версии AutoHotkey v2 (в альфа стадии уже довольно длительное время и неизвестно когда оно релизнется, но когда-то же это произойдёт?) из все выпилили :(

Offline
Posts: 294
Joined: Tue Jul 27, 2010 11:18 pm

Post by Serge Yolkin »

Drugmix wrote:~250шт
Это вторая версия не вышла. А в военное время до тысячи доходит... Пошол фигеть.

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

YuS wrote:Можно попытаться как-то так соорудить шаблон:

Code: Select all

([^;,`]*(?!`,)|[^,;]*?`,[^,;`]*?)*
Это не выход, ведь кол-во `, в одном аргументе может быть любым. Представляете насколько распухнут 250 правила с 0-11 аргументами, если я для каждого хотя бы 5-ого аргумента добавлю проверок на случай до 7 употреблений `, в них?
И как будут выглядеть эти правила? RegEx и так-то трудночитаемый, а тут вообще будет ад.

YuS
Offline
Posts: 513
Joined: Sun Sep 15, 2013 8:25 am
Location: 013 в Тентуре, семь по Спирали, налево от Большой Медведицы

Post by YuS »

Drugmix wrote: Это не выход, ведь кол-во `, в одном аргументе может быть любым.
А на практике попробовали?
Drugmix wrote: Представляете насколько распухнут 250 правила с 0-11 аргументами, если я для каждого хотя бы 5-ого аргумента добавлю проверок на случай до 7 употреблений `, в них?
И как будут выглядеть эти правила? RegEx и так-то трудночитаемый, а тут вообще будет ад.
Представляю, но ведь для того и существуют регулярки. Ок, может тот вариант и не совсем правильный... тогда попробуйте так:

Code: Select all

([^;,`]*(?!`,)|(?:[^`,;]*(?:`,)?))*?
тест - в AP тоже работает.

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

YuS
я тоже сначала попробовал, но у меня работало только в случае 1 аргумента, что и так работает если использовать просто .*
а сейчас покрутил Ваше правило ещё и нашёл ошибку в своей части правила, сейчас немного подправил - первые результаты очень хороши: в большинстве тестов сработало очень ОК.

Сейчас пытаюсь подправить правило и для остальных случаев.
Пока ломается на ` без запятой после неё.

И ещё: я сразу не сказал, т.к. не ожидал тут получить рабочее решение, но ведь и ; надо распознавать как часть аргумента у команды, если она экранирована. Пока большинство проваленных тестов как раз на строках с комментарием в конце.

Спасибо большое за Ваш вариант.

YuS
Offline
Posts: 513
Joined: Sun Sep 15, 2013 8:25 am
Location: 013 в Тентуре, семь по Спирали, налево от Большой Медведицы

Post by YuS »

Drugmix wrote: Сейчас пытаюсь подправить правило и для остальных случаев.
Пока ломается на ` без запятой после неё.

И ещё: я сразу не сказал, т.к. не ожидал тут получить рабочее решение, но ведь и ; надо распознавать как часть аргумента у команды, если она экранирована. Пока большинство проваленных тестов как раз на строках с комментарием в конце.
Необходим пример строки с возможными вариантами, чтобы было проще шаблон составить.

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

YuS
сейчас я использую такой шаблон:

Code: Select all

0	"^\s*(((Try)|(Else))(?:\s*,\s*|\s+)|(.{1,38}(?=::))(?:::))?\s*(#IfWinActive\b)(?:\s*,\s*?)?([^;,`]*(?!`,)|(?:[^`,;]*(?:`,)?))*?((?:\s*,\s*?)([^;,`]*(?!`,)|(?:[^`,;]*(?:`,)?))*?)?(\s+;.*)?$" `\3=(4,${OP},0) \4=(4,${IF},0) \5=(2,${STR},0) \6=(2,${OP},0) \7=(2,${ATTR},#ff0000) \9=(2,${ATTR},#00ff00) \10=(3,${COMM},0)`
:
SHOULD WORK:

#IfWinActive
MButton::#IfWinActive
Try #IfWinActive
Else #IfWinActive
Try,#IfWinActive
Else,#IfWinActive

#IfWinActive,
MButton::#IfWinActive,
Try #IfWinActive,
Else #IfWinActive,
Try,#IfWinActive,
Else,#IfWinActive,

#IfWinActive,,
MButton::#IfWinActive,,
Try #IfWinActive,,
Else #IfWinActive,,
Try,#IfWinActive,,
Else,#IfWinActive,,

#IfWinActive arg1
MButton::#IfWinActive arg1
Try #IfWinActive arg1
Else #IfWinActive arg1
Try,#IfWinActive arg1
Else,#IfWinActive arg1

#IfWinActive,arg1
MButton::#IfWinActive,arg1
Try #IfWinActive,arg1
Else #IfWinActive,arg1
Try,#IfWinActive,arg1
Else,#IfWinActive,arg1

#IfWinActive arg1,
MButton::#IfWinActive arg1,
Try #IfWinActive arg1,
Else #IfWinActive arg1,
Try,#IfWinActive arg1,
Else,#IfWinActive arg1,

#IfWinActive,arg1,
MButton::#IfWinActive,arg1,
Try #IfWinActive,arg1,
Else #IfWinActive,arg1,
Try,#IfWinActive,arg1,
Else,#IfWinActive,arg1,

#IfWinActive arg1, arg2
MButton::#IfWinActive arg1, arg2
Try #IfWinActive arg1, arg2
Else #IfWinActive arg1, arg2
Try,#IfWinActive arg1, arg2
Else,#IfWinActive arg1, arg2

#IfWinActive arg1,arg2
MButton::#IfWinActive arg1,arg2
Try #IfWinActive arg1,arg2
Else #IfWinActive arg1,arg2
Try,#IfWinActive arg1,arg2
Else,#IfWinActive arg1,arg2

#IfWinActive,arg1, arg2
MButton::#IfWinActive,arg1, arg2
Try #IfWinActive,arg1, arg2
Else #IfWinActive,arg1, arg2
Try,#IfWinActive,arg1, arg2
Else,#IfWinActive,arg1, arg2

#IfWinActive,arg1,arg2
MButton::#IfWinActive,arg1,arg2
Try #IfWinActive,arg1,arg2
Else #IfWinActive,arg1,arg2
Try,#IfWinActive,arg1,arg2
Else,#IfWinActive,arg1,arg2

#IfWinActive ; comm
MButton::#IfWinActive ; comm
Try #IfWinActive ; comm
Else #IfWinActive ; comm
Try,#IfWinActive ; comm
Else,#IfWinActive ; comm

#IfWinActive, ; comm
MButton::#IfWinActive, ; comm
Try #IfWinActive, ; comm
Else #IfWinActive, ; comm
Try,#IfWinActive, ; comm
Else,#IfWinActive, ; comm

#IfWinActive,, ; comm
MButton::#IfWinActive,, ; comm
Try #IfWinActive,, ; comm
Else #IfWinActive,, ; comm
Try,#IfWinActive,, ; comm
Else,#IfWinActive,, ; comm

#IfWinActive arg1 ; comm
MButton::#IfWinActive arg1 ; comm
Try #IfWinActive arg1 ; comm
Else #IfWinActive arg1 ; comm
Try,#IfWinActive arg1 ; comm
Else,#IfWinActive arg1 ; comm

#IfWinActive,arg1 ; comm
MButton::#IfWinActive,arg1 ; comm
Try #IfWinActive,arg1 ; comm
Else #IfWinActive,arg1 ; comm
Try,#IfWinActive,arg1 ; comm
Else,#IfWinActive,arg1 ; comm

#IfWinActive arg1, ; comm
MButton::#IfWinActive arg1, ; comm
Try #IfWinActive arg1, ; comm
Else #IfWinActive arg1, ; comm
Try,#IfWinActive arg1, ; comm
Else,#IfWinActive arg1, ; comm

#IfWinActive,arg1, ; comm
MButton::#IfWinActive,arg1, ; comm
Try #IfWinActive,arg1, ; comm
Else #IfWinActive,arg1, ; comm
Try,#IfWinActive,arg1, ; comm
Else,#IfWinActive,arg1, ; comm

#IfWinActive arg1, arg2 ; comm
MButton::#IfWinActive arg1, arg2 ; comm
Try #IfWinActive arg1, arg2 ; comm
Else #IfWinActive arg1, arg2 ; comm
Try,#IfWinActive arg1, arg2 ; comm
Else,#IfWinActive arg1, arg2 ; comm

#IfWinActive arg1,arg2 ; comm
MButton::#IfWinActive arg1,arg2 ; comm
Try #IfWinActive arg1,arg2 ; comm
Else #IfWinActive arg1,arg2 ; comm
Try,#IfWinActive arg1,arg2 ; comm
Else,#IfWinActive arg1,arg2 ; comm

#IfWinActive,arg1, arg2 ; comm
MButton::#IfWinActive,arg1, arg2 ; comm
Try #IfWinActive,arg1, arg2 ; comm
Else #IfWinActive,arg1, arg2 ; comm
Try,#IfWinActive,arg1, arg2 ; comm
Else,#IfWinActive,arg1, arg2 ; comm

#IfWinActive,arg1,arg2 ; comm
MButton::#IfWinActive,arg1,arg2 ; comm
Try #IfWinActive,arg1,arg2 ; comm
Else #IfWinActive,arg1,arg2 ; comm
Try,#IfWinActive,arg1,arg2 ; comm
Else,#IfWinActive,arg1,arg2 ; comm

#IfWinActive ar`,g1
MButton::#IfWinActive ar`,g1
Try #IfWinActive ar`,g1
Else #IfWinActive ar`,g1
Try,#IfWinActive ar`,g1
Else,#IfWinActive ar`,g1

#IfWinActive,ar`,g1
MButton::#IfWinActive,ar`,g1
Try #IfWinActive,ar`,g1
Else #IfWinActive,ar`,g1
Try,#IfWinActive,ar`,g1
Else,#IfWinActive,ar`,g1

#IfWinActive ar`,g1,
MButton::#IfWinActive ar`,g1,
Try #IfWinActive ar`,g1,
Else #IfWinActive ar`,g1,
Try,#IfWinActive ar`,g1,
Else,#IfWinActive ar`,g1,

#IfWinActive,ar`,g1,
MButton::#IfWinActive,ar`,g1,
Try #IfWinActive,ar`,g1,
Else #IfWinActive,ar`,g1,
Try,#IfWinActive,ar`,g1,
Else,#IfWinActive,ar`,g1,

#IfWinActive ar`,g1, ar`,g2
MButton::#IfWinActive ar`,g1, ar`,g2
Try #IfWinActive ar`,g1, ar`,g2
Else #IfWinActive ar`,g1, ar`,g2
Try,#IfWinActive ar`,g1, ar`,g2
Else,#IfWinActive ar`,g1, ar`,g2

#IfWinActive ar`,g1,ar`,g2
MButton::#IfWinActive ar`,g1,ar`,g2
Try #IfWinActive ar`,g1,ar`,g2
Else #IfWinActive ar`,g1,ar`,g2
Try,#IfWinActive ar`,g1,ar`,g2
Else,#IfWinActive ar`,g1,ar`,g2

#IfWinActive,ar`,g1, ar`,g2
MButton::#IfWinActive,ar`,g1, ar`,g2
Try #IfWinActive,ar`,g1, ar`,g2
Else #IfWinActive,ar`,g1, ar`,g2
Try,#IfWinActive,ar`,g1, ar`,g2
Else,#IfWinActive,ar`,g1, ar`,g2

#IfWinActive,ar`,g1,ar`,g2
MButton::#IfWinActive,ar`,g1,ar`,g2
Try #IfWinActive,ar`,g1,ar`,g2
Else #IfWinActive,ar`,g1,ar`,g2
Try,#IfWinActive,ar`,g1,ar`,g2
Else,#IfWinActive,ar`,g1,ar`,g2

#IfWinActive ; comm
MButton::#IfWinActive ; comm
Try #IfWinActive ; comm
Else #IfWinActive ; comm
Try,#IfWinActive ; comm
Else,#IfWinActive ; comm

#IfWinActive, ; comm
MButton::#IfWinActive, ; comm
Try #IfWinActive, ; comm
Else #IfWinActive, ; comm
Try,#IfWinActive, ; comm
Else,#IfWinActive, ; comm

#IfWinActive,, ; comm
MButton::#IfWinActive,, ; comm
Try #IfWinActive,, ; comm
Else #IfWinActive,, ; comm
Try,#IfWinActive,, ; comm
Else,#IfWinActive,, ; comm

#IfWinActive ar`,g1 ; comm
MButton::#IfWinActive ar`,g1 ; comm
Try #IfWinActive ar`,g1 ; comm
Else #IfWinActive ar`,g1 ; comm
Try,#IfWinActive ar`,g1 ; comm
Else,#IfWinActive ar`,g1 ; comm

#IfWinActive,ar`,g1 ; comm
MButton::#IfWinActive,ar`,g1 ; comm
Try #IfWinActive,ar`,g1 ; comm
Else #IfWinActive,ar`,g1 ; comm
Try,#IfWinActive,ar`,g1 ; comm
Else,#IfWinActive,ar`,g1 ; comm

#IfWinActive ar`,g1, ; comm
MButton::#IfWinActive ar`,g1, ; comm
Try #IfWinActive ar`,g1, ; comm
Else #IfWinActive ar`,g1, ; comm
Try,#IfWinActive ar`,g1, ; comm
Else,#IfWinActive ar`,g1, ; comm

#IfWinActive,ar`,g1, ; comm
MButton::#IfWinActive,ar`,g1, ; comm
Try #IfWinActive,ar`,g1, ; comm
Else #IfWinActive,ar`,g1, ; comm
Try,#IfWinActive,ar`,g1, ; comm
Else,#IfWinActive,ar`,g1, ; comm

#IfWinActive ar`,g1, ar`,g2 ; comm
MButton::#IfWinActive ar`,g1, ar`,g2 ; comm
Try #IfWinActive ar`,g1, ar`,g2 ; comm
Else #IfWinActive ar`,g1, ar`,g2 ; comm
Try,#IfWinActive ar`,g1, ar`,g2 ; comm
Else,#IfWinActive ar`,g1, ar`,g2 ; comm

#IfWinActive ar`,g1,ar`,g2 ; comm
MButton::#IfWinActive ar`,g1,ar`,g2 ; comm
Try #IfWinActive ar`,g1,ar`,g2 ; comm
Else #IfWinActive ar`,g1,ar`,g2 ; comm
Try,#IfWinActive ar`,g1,ar`,g2 ; comm
Else,#IfWinActive ar`,g1,ar`,g2 ; comm

#IfWinActive,ar`,g1, ar`,g2 ; comm
MButton::#IfWinActive,ar`,g1, ar`,g2 ; comm
Try #IfWinActive,ar`,g1, ar`,g2 ; comm
Else #IfWinActive,ar`,g1, ar`,g2 ; comm
Try,#IfWinActive,ar`,g1, ar`,g2 ; comm
Else,#IfWinActive,ar`,g1, ar`,g2 ; comm

#IfWinActive,ar`,g1,ar`,g2 ; comm
MButton::#IfWinActive,ar`,g1,ar`,g2 ; comm
Try #IfWinActive,ar`,g1,ar`,g2 ; comm
Else #IfWinActive,ar`,g1,ar`,g2 ; comm
Try,#IfWinActive,ar`,g1,ar`,g2 ; comm
Else,#IfWinActive,ar`,g1,ar`,g2 ; comm


SHOULD FAIL:
#IfWinActivearg1
Try#IfWinActive arg1
Else#IfWinActive arg1
::#IfWinActive,arg1
#IfWinActive; comm
#IfWinActive arg1; comm
#IfWinActive,arg1; comm

#IfWinActive arg1, arg2; comm
#IfWinActive,arg1,arg2; comm
#IfWinActive , arg2; comm
#IfWinActive,,arg2; comm

YuS
Offline
Posts: 513
Joined: Sun Sep 15, 2013 8:25 am
Location: 013 в Тентуре, семь по Спирали, налево от Большой Медведицы

Post by YuS »

Drugmix wrote: сейчас я использую такой шаблон:
...
и проверяю его на этих примерах:
Не совсем понял. Если это регулярка для QuotesRE, тогда она не пойдет, т.е. не будет работать, если увеличить количество аргументов в строке. Получается: надо захватывать все аргументы и подсвечивать их, либо на каждый аргумент писать отдельную группу...
В общем, мало информации, уточнить бы, что куда и зачем...

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

YuS
да, это регулярка для QuotesRE. И да, я обычно делал захват каждого аргумента (это необходимо для того, чтобы иметь возможность разным аргументам назначать разные цвета).
Синтаксис команды #IfWinActive в autohotkey такой:

Code: Select all

#IfWinActive [, WinTitle, WinText]
в квадратных скобках отмечены опциональные параметры.
Т.е. эта команда может вызываться с 0-2 аргументами (а если она вызывается с 1 аргументом, то это может быть любой аргумент: первый или второй).
+ В конце каждой строки возможно наличие строчного комментария, который должен начинаться с любого пробельного символа и идущей за ним точкой с запятой. Если точка с запятой идёт вплотную к коду - она будет считаться частью кода.
Если аргументу надо передать Delimiter (запятую) или CommentFlag (точку с запятой) - их надо экранировать добавив перед ними EscapeChar (backtick a.k.a обратную кавычку a.k.a `) вот так: `, и `;.
В принципе, экранирование точки с запятой не всегда обязательно: если после текста аргумента она идёт вплотную к этому тексту и перед ней нет пробельного символа - то она уже будет воспринята как часть аргумента, но т.к. экранирование даже в таком случае ничего не сломает - то лучше принять, что точку с запятой надо экранировать всегда, когда хочется, чтобы она была частью аргумента.
После команды и перед первым аргументом (если он не пустой) - запятая опциональна.

Т.к. аргументы можно "опускать", то нужно считать валидными и такие употребления:

Code: Select all

#IfWinActive
#IfWinActive,
#IfWinActive,,
#IfWinActive    ,
#IfWinActive    ,    ,
#IfWinActive arg1
#IfWinActive,arg1
#IfWinActive arg1,
#IfWinActive,arg1,
#IfWinActive,arg1,arg2
#IfWinActive arg1,arg2
#IfWinActive,,arg2
Но так, как аргументов не может быть более 2, то надо чтобы правило подсветки не срабатывало бы на этих строках:

Code: Select all

#IfWinActive,arg1,arg2,arg3
#IfWinActive,arg1,arg2,
#IfWinActive,arg1,,
#IfWinActive,,,
и на строках с бо́льшим кол-вом аргументов.

Offline
Site Admin
Posts: 6403
Joined: Thu Jul 06, 2006 7:20 am

Post by Instructor »

Drugmix wrote:оно стало приводить к краху АкелПада
Serge Yolkin wrote:удалось грохнуть и тестовую
Тестовая

Offline
Posts: 294
Joined: Tue Jul 27, 2010 11:18 pm

Post by Serge Yolkin »

Instructor
Предыдущая проблема решена, но

Code: Select all

^[a-]+
роняет обе тестовые и последнюю стабильную. ([a-] получилось в ходе редактирования, z набрать уже не успел)

Offline
Posts: 294
Joined: Tue Jul 27, 2010 11:18 pm

Post by Serge Yolkin »

Ещё: все три версии считают выражение

Code: Select all

^[^\n\r]+\,
невалидным, независимо от того экранирована запятая, или нет (проверяю всё в QSearch). Что я делаю не так?

Точнее, ничего не ищет. Проблема, вероятно, в [^... :

Code: Select all

^[^\d]+\,
не работает, а
^[\w]+\,
вполне
Last edited by Serge Yolkin on Wed Jan 15, 2014 6:37 pm, edited 1 time in total.

YuS
Offline
Posts: 513
Joined: Sun Sep 15, 2013 8:25 am
Location: 013 в Тентуре, семь по Спирали, налево от Большой Медведицы

Post by YuS »

Drugmix wrote: да, это регулярка для QuotesRE.
Как-то так:

Code: Select all

0   "^\s*(?:(Try)?(Else)?(?:\s*?,\s*?|\s+?)|(.{1,38}(?=::))(?:::))?\s*(#IfWinActive\b)(?:\s*?,\s*?|\s*?)??([^,`\s]*(?!`,)|(?:[^`,\s]*(?:`,)?)*)?(?:\s*?,\s*?)?([^,`\s]*(?!`,)|(?:[^`,\s]*(?:`,)?)*)?(\s+;.*)?[\s]*$" `\1=(4,${OP},0) \2=(4,${IF},0) \3=(2,${STR},0) \4=(2,${OP},0) \5=(2,${ATTR},#ff0000) \6=(2,${ATTR},#00ff00) \7=(3,${COMM},0)`

Offline
Site Admin
Posts: 6403
Joined: Thu Jul 06, 2006 7:20 am

Post by Instructor »

Serge Yolkin wrote:но

Code: Select all

^[a-]+
роняет...
Тестовая
Serge Yolkin wrote:^[^\d]+\,
не работает
^[^\d]+?,
Post Reply